mms2r 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/History.txt +4 -0
  2. data/Manifest.txt +54 -0
  3. data/README.txt +81 -0
  4. data/Rakefile +30 -0
  5. data/conf/mms2r_cingularmedia_transform.yml +6 -0
  6. data/conf/mms2r_sprintmedia_ignore.yml +10 -0
  7. data/conf/mms2r_tmobilemedia_ignore.yml +17 -0
  8. data/conf/mms2r_verizonmedia_ignore.yml +3 -0
  9. data/lib/mms2r.rb +3 -0
  10. data/lib/mms2r/cingular_media.rb +11 -0
  11. data/lib/mms2r/media.rb +345 -0
  12. data/lib/mms2r/mmode_media.rb +13 -0
  13. data/lib/mms2r/sprint_media.rb +50 -0
  14. data/lib/mms2r/tmobile_media.rb +11 -0
  15. data/lib/mms2r/verizon_media.rb +11 -0
  16. data/lib/mms2r/version.rb +12 -0
  17. data/lib/vendor/text/format.rb +1466 -0
  18. data/lib/vendor/tmail.rb +3 -0
  19. data/lib/vendor/tmail/address.rb +242 -0
  20. data/lib/vendor/tmail/attachments.rb +39 -0
  21. data/lib/vendor/tmail/base64.rb +71 -0
  22. data/lib/vendor/tmail/config.rb +69 -0
  23. data/lib/vendor/tmail/encode.rb +467 -0
  24. data/lib/vendor/tmail/facade.rb +552 -0
  25. data/lib/vendor/tmail/header.rb +914 -0
  26. data/lib/vendor/tmail/info.rb +35 -0
  27. data/lib/vendor/tmail/loader.rb +1 -0
  28. data/lib/vendor/tmail/mail.rb +447 -0
  29. data/lib/vendor/tmail/mailbox.rb +433 -0
  30. data/lib/vendor/tmail/mbox.rb +1 -0
  31. data/lib/vendor/tmail/net.rb +280 -0
  32. data/lib/vendor/tmail/obsolete.rb +135 -0
  33. data/lib/vendor/tmail/parser.rb +1522 -0
  34. data/lib/vendor/tmail/port.rb +377 -0
  35. data/lib/vendor/tmail/quoting.rb +131 -0
  36. data/lib/vendor/tmail/scanner.rb +41 -0
  37. data/lib/vendor/tmail/scanner_r.rb +263 -0
  38. data/lib/vendor/tmail/stringio.rb +277 -0
  39. data/lib/vendor/tmail/tmail.rb +1 -0
  40. data/lib/vendor/tmail/utils.rb +238 -0
  41. data/test/files/dot.jpg +0 -0
  42. data/test/files/sprint-image-01.mail +195 -0
  43. data/test/files/sprint-text-01.mail +8 -0
  44. data/test/files/sprint-video-01.mail +195 -0
  45. data/test/files/sprint.mov +0 -0
  46. data/test/files/verizon-image-01.mail +815 -0
  47. data/test/files/verizon-text-01.mail +11 -0
  48. data/test/files/verizon-video-01.mail +336 -0
  49. data/test/test_mms2r_cingular.rb +52 -0
  50. data/test/test_mms2r_media.rb +311 -0
  51. data/test/test_mms2r_mmode.rb +52 -0
  52. data/test/test_mms2r_sprint.rb +154 -0
  53. data/test/test_mms2r_tmobile.rb +169 -0
  54. data/test/test_mms2r_verizon.rb +74 -0
  55. metadata +130 -0
@@ -0,0 +1,433 @@
1
+ #
2
+ # mailbox.rb
3
+ #
4
+ #--
5
+ # Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining
8
+ # a copy of this software and associated documentation files (the
9
+ # "Software"), to deal in the Software without restriction, including
10
+ # without limitation the rights to use, copy, modify, merge, publish,
11
+ # distribute, sublicense, and/or sell copies of the Software, and to
12
+ # permit persons to whom the Software is furnished to do so, subject to
13
+ # the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+ #
26
+ # Note: Originally licensed under LGPL v2+. Using MIT license for Rails
27
+ # with permission of Minero Aoki.
28
+ #++
29
+
30
+ require 'tmail/port'
31
+ require 'socket'
32
+ require 'mutex_m'
33
+
34
+
35
+ unless [].respond_to?(:sort_by)
36
+ module Enumerable#:nodoc:
37
+ def sort_by
38
+ map {|i| [yield(i), i] }.sort {|a,b| a.first <=> b.first }.map {|i| i[1] }
39
+ end
40
+ end
41
+ end
42
+
43
+
44
+ module TMail
45
+
46
+ class MhMailbox
47
+
48
+ PORT_CLASS = MhPort
49
+
50
+ def initialize( dir )
51
+ edir = File.expand_path(dir)
52
+ raise ArgumentError, "not directory: #{dir}"\
53
+ unless FileTest.directory? edir
54
+ @dirname = edir
55
+ @last_file = nil
56
+ @last_atime = nil
57
+ end
58
+
59
+ def directory
60
+ @dirname
61
+ end
62
+
63
+ alias dirname directory
64
+
65
+ attr_accessor :last_atime
66
+
67
+ def inspect
68
+ "#<#{self.class} #{@dirname}>"
69
+ end
70
+
71
+ def close
72
+ end
73
+
74
+ def new_port
75
+ PORT_CLASS.new(next_file_name())
76
+ end
77
+
78
+ def each_port
79
+ mail_files().each do |path|
80
+ yield PORT_CLASS.new(path)
81
+ end
82
+ @last_atime = Time.now
83
+ end
84
+
85
+ alias each each_port
86
+
87
+ def reverse_each_port
88
+ mail_files().reverse_each do |path|
89
+ yield PORT_CLASS.new(path)
90
+ end
91
+ @last_atime = Time.now
92
+ end
93
+
94
+ alias reverse_each reverse_each_port
95
+
96
+ # old #each_mail returns Port
97
+ #def each_mail
98
+ # each_port do |port|
99
+ # yield Mail.new(port)
100
+ # end
101
+ #end
102
+
103
+ def each_new_port( mtime = nil, &block )
104
+ mtime ||= @last_atime
105
+ return each_port(&block) unless mtime
106
+ return unless File.mtime(@dirname) >= mtime
107
+
108
+ mail_files().each do |path|
109
+ yield PORT_CLASS.new(path) if File.mtime(path) > mtime
110
+ end
111
+ @last_atime = Time.now
112
+ end
113
+
114
+ private
115
+
116
+ def mail_files
117
+ Dir.entries(@dirname)\
118
+ .select {|s| /\A\d+\z/ === s }\
119
+ .map {|s| s.to_i }\
120
+ .sort\
121
+ .map {|i| "#{@dirname}/#{i}" }\
122
+ .select {|path| FileTest.file? path }
123
+ end
124
+
125
+ def next_file_name
126
+ unless n = @last_file
127
+ n = 0
128
+ Dir.entries(@dirname)\
129
+ .select {|s| /\A\d+\z/ === s }\
130
+ .map {|s| s.to_i }.sort\
131
+ .each do |i|
132
+ next unless FileTest.file? "#{@dirname}/#{i}"
133
+ n = i
134
+ end
135
+ end
136
+ begin
137
+ n += 1
138
+ end while FileTest.exist? "#{@dirname}/#{n}"
139
+ @last_file = n
140
+
141
+ "#{@dirname}/#{n}"
142
+ end
143
+
144
+ end # MhMailbox
145
+
146
+ MhLoader = MhMailbox
147
+
148
+
149
+ class UNIXMbox
150
+
151
+ def UNIXMbox.lock( fname )
152
+ begin
153
+ f = File.open(fname)
154
+ f.flock File::LOCK_EX
155
+ yield f
156
+ ensure
157
+ f.flock File::LOCK_UN
158
+ f.close if f and not f.closed?
159
+ end
160
+ end
161
+
162
+ class << self
163
+ alias newobj new
164
+ end
165
+
166
+ def UNIXMbox.new( fname, tmpdir = nil, readonly = false )
167
+ tmpdir = ENV['TEMP'] || ENV['TMP'] || '/tmp'
168
+ newobj(fname, "#{tmpdir}/ruby_tmail_#{$$}_#{rand()}", readonly, false)
169
+ end
170
+
171
+ def UNIXMbox.static_new( fname, dir, readonly = false )
172
+ newobj(fname, dir, readonly, true)
173
+ end
174
+
175
+ def initialize( fname, mhdir, readonly, static )
176
+ @filename = fname
177
+ @readonly = readonly
178
+ @closed = false
179
+
180
+ Dir.mkdir mhdir
181
+ @real = MhMailbox.new(mhdir)
182
+ @finalizer = UNIXMbox.mkfinal(@real, @filename, !@readonly, !static)
183
+ ObjectSpace.define_finalizer self, @finalizer
184
+ end
185
+
186
+ def UNIXMbox.mkfinal( mh, mboxfile, writeback_p, cleanup_p )
187
+ lambda {
188
+ if writeback_p
189
+ lock(mboxfile) {|f|
190
+ mh.each_port do |port|
191
+ f.puts create_from_line(port)
192
+ port.ropen {|r|
193
+ f.puts r.read
194
+ }
195
+ end
196
+ }
197
+ end
198
+ if cleanup_p
199
+ Dir.foreach(mh.dirname) do |fname|
200
+ next if /\A\.\.?\z/ === fname
201
+ File.unlink "#{mh.dirname}/#{fname}"
202
+ end
203
+ Dir.rmdir mh.dirname
204
+ end
205
+ }
206
+ end
207
+
208
+ # make _From line
209
+ def UNIXMbox.create_from_line( port )
210
+ sprintf 'From %s %s',
211
+ fromaddr(), TextUtils.time2str(File.mtime(port.filename))
212
+ end
213
+
214
+ def UNIXMbox.fromaddr
215
+ h = HeaderField.new_from_port(port, 'Return-Path') ||
216
+ HeaderField.new_from_port(port, 'From') or return 'nobody'
217
+ a = h.addrs[0] or return 'nobody'
218
+ a.spec
219
+ end
220
+ private_class_method :fromaddr
221
+
222
+ def close
223
+ return if @closed
224
+
225
+ ObjectSpace.undefine_finalizer self
226
+ @finalizer.call
227
+ @finalizer = nil
228
+ @real = nil
229
+ @closed = true
230
+ @updated = nil
231
+ end
232
+
233
+ def each_port( &block )
234
+ close_check
235
+ update
236
+ @real.each_port(&block)
237
+ end
238
+
239
+ alias each each_port
240
+
241
+ def reverse_each_port( &block )
242
+ close_check
243
+ update
244
+ @real.reverse_each_port(&block)
245
+ end
246
+
247
+ alias reverse_each reverse_each_port
248
+
249
+ # old #each_mail returns Port
250
+ #def each_mail( &block )
251
+ # each_port do |port|
252
+ # yield Mail.new(port)
253
+ # end
254
+ #end
255
+
256
+ def each_new_port( mtime = nil )
257
+ close_check
258
+ update
259
+ @real.each_new_port(mtime) {|p| yield p }
260
+ end
261
+
262
+ def new_port
263
+ close_check
264
+ @real.new_port
265
+ end
266
+
267
+ private
268
+
269
+ def close_check
270
+ @closed and raise ArgumentError, 'accessing already closed mbox'
271
+ end
272
+
273
+ def update
274
+ return if FileTest.zero?(@filename)
275
+ return if @updated and File.mtime(@filename) < @updated
276
+ w = nil
277
+ port = nil
278
+ time = nil
279
+ UNIXMbox.lock(@filename) {|f|
280
+ begin
281
+ f.each do |line|
282
+ if /\AFrom / === line
283
+ w.close if w
284
+ File.utime time, time, port.filename if time
285
+
286
+ port = @real.new_port
287
+ w = port.wopen
288
+ time = fromline2time(line)
289
+ else
290
+ w.print line if w
291
+ end
292
+ end
293
+ ensure
294
+ if w and not w.closed?
295
+ w.close
296
+ File.utime time, time, port.filename if time
297
+ end
298
+ end
299
+ f.truncate(0) unless @readonly
300
+ @updated = Time.now
301
+ }
302
+ end
303
+
304
+ def fromline2time( line )
305
+ m = /\AFrom \S+ \w+ (\w+) (\d+) (\d+):(\d+):(\d+) (\d+)/.match(line) \
306
+ or return nil
307
+ Time.local(m[6].to_i, m[1], m[2].to_i, m[3].to_i, m[4].to_i, m[5].to_i)
308
+ end
309
+
310
+ end # UNIXMbox
311
+
312
+ MboxLoader = UNIXMbox
313
+
314
+
315
+ class Maildir
316
+
317
+ extend Mutex_m
318
+
319
+ PORT_CLASS = MaildirPort
320
+
321
+ @seq = 0
322
+ def Maildir.unique_number
323
+ synchronize {
324
+ @seq += 1
325
+ return @seq
326
+ }
327
+ end
328
+
329
+ def initialize( dir = nil )
330
+ @dirname = dir || ENV['MAILDIR']
331
+ raise ArgumentError, "not directory: #{@dirname}"\
332
+ unless FileTest.directory? @dirname
333
+ @new = "#{@dirname}/new"
334
+ @tmp = "#{@dirname}/tmp"
335
+ @cur = "#{@dirname}/cur"
336
+ end
337
+
338
+ def directory
339
+ @dirname
340
+ end
341
+
342
+ def inspect
343
+ "#<#{self.class} #{@dirname}>"
344
+ end
345
+
346
+ def close
347
+ end
348
+
349
+ def each_port
350
+ mail_files(@cur).each do |path|
351
+ yield PORT_CLASS.new(path)
352
+ end
353
+ end
354
+
355
+ alias each each_port
356
+
357
+ def reverse_each_port
358
+ mail_files(@cur).reverse_each do |path|
359
+ yield PORT_CLASS.new(path)
360
+ end
361
+ end
362
+
363
+ alias reverse_each reverse_each_port
364
+
365
+ def new_port
366
+ fname = nil
367
+ tmpfname = nil
368
+ newfname = nil
369
+
370
+ begin
371
+ fname = "#{Time.now.to_i}.#{$$}_#{Maildir.unique_number}.#{Socket.gethostname}"
372
+
373
+ tmpfname = "#{@tmp}/#{fname}"
374
+ newfname = "#{@new}/#{fname}"
375
+ end while FileTest.exist? tmpfname
376
+
377
+ if block_given?
378
+ File.open(tmpfname, 'w') {|f| yield f }
379
+ File.rename tmpfname, newfname
380
+ PORT_CLASS.new(newfname)
381
+ else
382
+ File.open(tmpfname, 'w') {|f| f.write "\n\n" }
383
+ PORT_CLASS.new(tmpfname)
384
+ end
385
+ end
386
+
387
+ def each_new_port
388
+ mail_files(@new).each do |path|
389
+ dest = @cur + '/' + File.basename(path)
390
+ File.rename path, dest
391
+ yield PORT_CLASS.new(dest)
392
+ end
393
+
394
+ check_tmp
395
+ end
396
+
397
+ TOO_OLD = 60 * 60 * 36 # 36 hour
398
+
399
+ def check_tmp
400
+ old = Time.now.to_i - TOO_OLD
401
+
402
+ each_filename(@tmp) do |full, fname|
403
+ if FileTest.file? full and
404
+ File.stat(full).mtime.to_i < old
405
+ File.unlink full
406
+ end
407
+ end
408
+ end
409
+
410
+ private
411
+
412
+ def mail_files( dir )
413
+ Dir.entries(dir)\
414
+ .select {|s| s[0] != ?. }\
415
+ .sort_by {|s| s.slice(/\A\d+/).to_i }\
416
+ .map {|s| "#{dir}/#{s}" }\
417
+ .select {|path| FileTest.file? path }
418
+ end
419
+
420
+ def each_filename( dir )
421
+ Dir.foreach(dir) do |fname|
422
+ path = "#{dir}/#{fname}"
423
+ if fname[0] != ?. and FileTest.file? path
424
+ yield path, fname
425
+ end
426
+ end
427
+ end
428
+
429
+ end # Maildir
430
+
431
+ MaildirLoader = Maildir
432
+
433
+ end # module TMail
@@ -0,0 +1 @@
1
+ require 'tmail/mailbox'
@@ -0,0 +1,280 @@
1
+ #
2
+ # net.rb
3
+ #
4
+ #--
5
+ # Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining
8
+ # a copy of this software and associated documentation files (the
9
+ # "Software"), to deal in the Software without restriction, including
10
+ # without limitation the rights to use, copy, modify, merge, publish,
11
+ # distribute, sublicense, and/or sell copies of the Software, and to
12
+ # permit persons to whom the Software is furnished to do so, subject to
13
+ # the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+ #
26
+ # Note: Originally licensed under LGPL v2+. Using MIT license for Rails
27
+ # with permission of Minero Aoki.
28
+ #++
29
+
30
+ require 'nkf'
31
+
32
+
33
+ module TMail
34
+
35
+ class Mail
36
+
37
+ def send_to( smtp )
38
+ do_send_to(smtp) do
39
+ ready_to_send
40
+ end
41
+ end
42
+
43
+ def send_text_to( smtp )
44
+ do_send_to(smtp) do
45
+ ready_to_send
46
+ mime_encode
47
+ end
48
+ end
49
+
50
+ def do_send_to( smtp )
51
+ from = from_address or raise ArgumentError, 'no from address'
52
+ (dests = destinations).empty? and raise ArgumentError, 'no receipient'
53
+ yield
54
+ send_to_0 smtp, from, dests
55
+ end
56
+ private :do_send_to
57
+
58
+ def send_to_0( smtp, from, to )
59
+ smtp.ready(from, to) do |f|
60
+ encoded "\r\n", 'j', f, ''
61
+ end
62
+ end
63
+
64
+ def ready_to_send
65
+ delete_no_send_fields
66
+ add_message_id
67
+ add_date
68
+ end
69
+
70
+ NOSEND_FIELDS = %w(
71
+ received
72
+ bcc
73
+ )
74
+
75
+ def delete_no_send_fields
76
+ NOSEND_FIELDS.each do |nm|
77
+ delete nm
78
+ end
79
+ delete_if {|n,v| v.empty? }
80
+ end
81
+
82
+ def add_message_id( fqdn = nil )
83
+ self.message_id = ::TMail::new_message_id(fqdn)
84
+ end
85
+
86
+ def add_date
87
+ self.date = Time.now
88
+ end
89
+
90
+ def mime_encode
91
+ if parts.empty?
92
+ mime_encode_singlepart
93
+ else
94
+ mime_encode_multipart true
95
+ end
96
+ end
97
+
98
+ def mime_encode_singlepart
99
+ self.mime_version = '1.0'
100
+ b = body
101
+ if NKF.guess(b) != NKF::BINARY
102
+ mime_encode_text b
103
+ else
104
+ mime_encode_binary b
105
+ end
106
+ end
107
+
108
+ def mime_encode_text( body )
109
+ self.body = NKF.nkf('-j -m0', body)
110
+ self.set_content_type 'text', 'plain', {'charset' => 'iso-2022-jp'}
111
+ self.encoding = '7bit'
112
+ end
113
+
114
+ def mime_encode_binary( body )
115
+ self.body = [body].pack('m')
116
+ self.set_content_type 'application', 'octet-stream'
117
+ self.encoding = 'Base64'
118
+ end
119
+
120
+ def mime_encode_multipart( top = true )
121
+ self.mime_version = '1.0' if top
122
+ self.set_content_type 'multipart', 'mixed'
123
+ e = encoding(nil)
124
+ if e and not /\A(?:7bit|8bit|binary)\z/i === e
125
+ raise ArgumentError,
126
+ 'using C.T.Encoding with multipart mail is not permitted'
127
+ end
128
+ end
129
+
130
+ def create_empty_mail
131
+ self.class.new(StringPort.new(''), @config)
132
+ end
133
+
134
+ def create_reply
135
+ setup_reply create_empty_mail()
136
+ end
137
+
138
+ def setup_reply( m )
139
+ if tmp = reply_addresses(nil)
140
+ m.to_addrs = tmp
141
+ end
142
+
143
+ mid = message_id(nil)
144
+ tmp = references(nil) || []
145
+ tmp.push mid if mid
146
+ m.in_reply_to = [mid] if mid
147
+ m.references = tmp unless tmp.empty?
148
+ m.subject = 'Re: ' + subject('').sub(/\A(?:\s*re:)+/i, '')
149
+
150
+ m
151
+ end
152
+
153
+ def create_forward
154
+ setup_forward create_empty_mail()
155
+ end
156
+
157
+ def setup_forward( mail )
158
+ m = Mail.new(StringPort.new(''))
159
+ m.body = decoded
160
+ m.set_content_type 'message', 'rfc822'
161
+ m.encoding = encoding('7bit')
162
+ mail.parts.push m
163
+ end
164
+
165
+ end
166
+
167
+
168
+ class DeleteFields
169
+
170
+ NOSEND_FIELDS = %w(
171
+ received
172
+ bcc
173
+ )
174
+
175
+ def initialize( nosend = nil, delempty = true )
176
+ @no_send_fields = nosend || NOSEND_FIELDS.dup
177
+ @delete_empty_fields = delempty
178
+ end
179
+
180
+ attr :no_send_fields
181
+ attr :delete_empty_fields, true
182
+
183
+ def exec( mail )
184
+ @no_send_fields.each do |nm|
185
+ delete nm
186
+ end
187
+ delete_if {|n,v| v.empty? } if @delete_empty_fields
188
+ end
189
+
190
+ end
191
+
192
+
193
+ class AddMessageId
194
+
195
+ def initialize( fqdn = nil )
196
+ @fqdn = fqdn
197
+ end
198
+
199
+ attr :fqdn, true
200
+
201
+ def exec( mail )
202
+ mail.message_id = ::TMail::new_msgid(@fqdn)
203
+ end
204
+
205
+ end
206
+
207
+
208
+ class AddDate
209
+
210
+ def exec( mail )
211
+ mail.date = Time.now
212
+ end
213
+
214
+ end
215
+
216
+
217
+ class MimeEncodeAuto
218
+
219
+ def initialize( s = nil, m = nil )
220
+ @singlepart_composer = s || MimeEncodeSingle.new
221
+ @multipart_composer = m || MimeEncodeMulti.new
222
+ end
223
+
224
+ attr :singlepart_composer
225
+ attr :multipart_composer
226
+
227
+ def exec( mail )
228
+ if mail._builtin_multipart?
229
+ then @multipart_composer
230
+ else @singlepart_composer end.exec mail
231
+ end
232
+
233
+ end
234
+
235
+
236
+ class MimeEncodeSingle
237
+
238
+ def exec( mail )
239
+ mail.mime_version = '1.0'
240
+ b = mail.body
241
+ if NKF.guess(b) != NKF::BINARY
242
+ on_text b
243
+ else
244
+ on_binary b
245
+ end
246
+ end
247
+
248
+ def on_text( body )
249
+ mail.body = NKF.nkf('-j -m0', body)
250
+ mail.set_content_type 'text', 'plain', {'charset' => 'iso-2022-jp'}
251
+ mail.encoding = '7bit'
252
+ end
253
+
254
+ def on_binary( body )
255
+ mail.body = [body].pack('m')
256
+ mail.set_content_type 'application', 'octet-stream'
257
+ mail.encoding = 'Base64'
258
+ end
259
+
260
+ end
261
+
262
+
263
+ class MimeEncodeMulti
264
+
265
+ def exec( mail, top = true )
266
+ mail.mime_version = '1.0' if top
267
+ mail.set_content_type 'multipart', 'mixed'
268
+ e = encoding(nil)
269
+ if e and not /\A(?:7bit|8bit|binary)\z/i === e
270
+ raise ArgumentError,
271
+ 'using C.T.Encoding with multipart mail is not permitted'
272
+ end
273
+ mail.parts.each do |m|
274
+ exec m, false if m._builtin_multipart?
275
+ end
276
+ end
277
+
278
+ end
279
+
280
+ end # module TMail