tmail 1.1.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 (102) hide show
  1. data/LICENSE +21 -0
  2. data/README +157 -0
  3. data/bat/changelog +19 -0
  4. data/bat/clobber/package +10 -0
  5. data/bat/compile +42 -0
  6. data/bat/config.yaml +8 -0
  7. data/bat/prepare +8 -0
  8. data/bat/publish +51 -0
  9. data/bat/rdoc +42 -0
  10. data/bat/release +12 -0
  11. data/bat/setup +1616 -0
  12. data/bat/stats +138 -0
  13. data/bat/tag +25 -0
  14. data/bat/test +25 -0
  15. data/ext/tmail/Makefile +25 -0
  16. data/ext/tmail/base64/MANIFEST +4 -0
  17. data/ext/tmail/base64/base64.c +264 -0
  18. data/ext/tmail/base64/depend +1 -0
  19. data/ext/tmail/base64/extconf.rb +38 -0
  20. data/ext/tmail/scanner_c/MANIFEST +4 -0
  21. data/ext/tmail/scanner_c/depend +1 -0
  22. data/ext/tmail/scanner_c/extconf.rb +38 -0
  23. data/ext/tmail/scanner_c/scanner_c.c +582 -0
  24. data/lib/tmail.rb +4 -0
  25. data/lib/tmail/Makefile +19 -0
  26. data/lib/tmail/address.rb +245 -0
  27. data/lib/tmail/attachments.rb +47 -0
  28. data/lib/tmail/base64.rb +75 -0
  29. data/lib/tmail/compat.rb +39 -0
  30. data/lib/tmail/config.rb +71 -0
  31. data/lib/tmail/core_extensions.rb +67 -0
  32. data/lib/tmail/encode.rb +524 -0
  33. data/lib/tmail/header.rb +931 -0
  34. data/lib/tmail/index.rb +8 -0
  35. data/lib/tmail/interface.rb +540 -0
  36. data/lib/tmail/loader.rb +1 -0
  37. data/lib/tmail/mail.rb +507 -0
  38. data/lib/tmail/mailbox.rb +435 -0
  39. data/lib/tmail/mbox.rb +1 -0
  40. data/lib/tmail/net.rb +282 -0
  41. data/lib/tmail/obsolete.rb +137 -0
  42. data/lib/tmail/parser.rb +1475 -0
  43. data/lib/tmail/parser.y +381 -0
  44. data/lib/tmail/port.rb +379 -0
  45. data/lib/tmail/quoting.rb +142 -0
  46. data/lib/tmail/require_arch.rb +56 -0
  47. data/lib/tmail/scanner.rb +44 -0
  48. data/lib/tmail/scanner_r.rb +263 -0
  49. data/lib/tmail/stringio.rb +279 -0
  50. data/lib/tmail/tmail.rb +1 -0
  51. data/lib/tmail/utils.rb +281 -0
  52. data/lib/tmail/version.rb +38 -0
  53. data/meta/icli.yaml +16 -0
  54. data/meta/tmail-1.1.1.roll +24 -0
  55. data/sample/data/multipart +23 -0
  56. data/sample/data/normal +29 -0
  57. data/sample/data/sendtest +5 -0
  58. data/sample/data/simple +14 -0
  59. data/sample/data/test +27 -0
  60. data/sample/extract-attachements.rb +33 -0
  61. data/sample/from-check.rb +26 -0
  62. data/sample/multipart.rb +26 -0
  63. data/sample/parse-bench.rb +68 -0
  64. data/sample/parse-test.rb +19 -0
  65. data/sample/sendmail.rb +94 -0
  66. data/test/extctrl.rb +6 -0
  67. data/test/fixtures/raw_base64_decoded_string +0 -0
  68. data/test/fixtures/raw_base64_email +83 -0
  69. data/test/fixtures/raw_base64_encoded_string +1 -0
  70. data/test/fixtures/raw_email +14 -0
  71. data/test/fixtures/raw_email10 +20 -0
  72. data/test/fixtures/raw_email11 +34 -0
  73. data/test/fixtures/raw_email12 +32 -0
  74. data/test/fixtures/raw_email13 +29 -0
  75. data/test/fixtures/raw_email2 +114 -0
  76. data/test/fixtures/raw_email3 +70 -0
  77. data/test/fixtures/raw_email4 +59 -0
  78. data/test/fixtures/raw_email5 +19 -0
  79. data/test/fixtures/raw_email6 +20 -0
  80. data/test/fixtures/raw_email7 +66 -0
  81. data/test/fixtures/raw_email8 +47 -0
  82. data/test/fixtures/raw_email9 +28 -0
  83. data/test/fixtures/raw_email_quoted_with_0d0a +14 -0
  84. data/test/fixtures/raw_email_simple +11 -0
  85. data/test/fixtures/raw_email_with_illegal_boundary +58 -0
  86. data/test/fixtures/raw_email_with_multipart_mixed_quoted_boundary +50 -0
  87. data/test/fixtures/raw_email_with_nested_attachment +100 -0
  88. data/test/fixtures/raw_email_with_partially_quoted_subject +14 -0
  89. data/test/fixtures/raw_email_with_quoted_illegal_boundary +58 -0
  90. data/test/kcode.rb +14 -0
  91. data/test/test_address.rb +1128 -0
  92. data/test/test_attachments.rb +35 -0
  93. data/test/test_base64.rb +63 -0
  94. data/test/test_encode.rb +77 -0
  95. data/test/test_header.rb +885 -0
  96. data/test/test_helper.rb +2 -0
  97. data/test/test_mail.rb +623 -0
  98. data/test/test_mbox.rb +126 -0
  99. data/test/test_port.rb +430 -0
  100. data/test/test_scanner.rb +209 -0
  101. data/test/test_utils.rb +37 -0
  102. metadata +205 -0
@@ -0,0 +1,38 @@
1
+ #
2
+ # version.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
+ module TMail #:nodoc:
31
+ module VERSION #:nodoc:
32
+ MAJOR = 1
33
+ MINOR = 1
34
+ TINY = 1
35
+
36
+ STRING = [MAJOR, MINOR, TINY].join('.')
37
+ end
38
+ end
@@ -0,0 +1,16 @@
1
+ ---
2
+ rubyforge:
3
+ project : tmail
4
+ username : transami
5
+
6
+ release:
7
+ store : pkg
8
+ package : tmail
9
+ notelog : log/Note.txt
10
+ changelog : log/Release.txt
11
+
12
+ publish: {}
13
+
14
+ announce:
15
+ message: README
16
+
@@ -0,0 +1,24 @@
1
+ ---
2
+ title : TMail
3
+ brief : Ruby Mail Handler
4
+ contact : Mikel Lindsaar <raasdnil AT gmail.com>
5
+ email : tmail-talk@rubyforge.org
6
+ authors :
7
+ - Minero Aoki
8
+ - Mikel Lindsaar
9
+
10
+ description:
11
+ TMail is a Ruby-based mail handler. It allows you
12
+ to compose stadards compliant emails in a
13
+ very Ruby-way.
14
+
15
+ formats: [tgz, gem]
16
+
17
+ #platforms: [ruby, unix, mswin32]
18
+
19
+ lib_path:
20
+ - lib/tmail
21
+
22
+ gem_path:
23
+ - lib
24
+
@@ -0,0 +1,23 @@
1
+ Date: Tue, 26 Jan 1999 23:17:34 +0900
2
+ From: aamine@dp.u-netsurf.ne.jp
3
+ To: ruby-list@netlab.co.jp
4
+ Mime-Version: 1.0
5
+ Content-Type: multipart/mixed;
6
+ boundary="Multipart_Tue_Jan_26_23:14:41_1999-1"
7
+ Content-Transfer-Encoding: 7bit
8
+
9
+ this is preamble
10
+
11
+ --Multipart_Tue_Jan_26_23:14:41_1999-1
12
+ Content-Type: text/plain; charset=iso-2022-jp
13
+
14
+ this is multi part body 1
15
+
16
+ --Multipart_Tue_Jan_26_23:14:41_1999-1
17
+ Content-Type: text/plain; charset=iso-2022-jp
18
+
19
+ multi part body, 2
20
+
21
+ --Multipart_Tue_Jan_26_23:14:41_1999-1--
22
+
23
+ epilogue
@@ -0,0 +1,29 @@
1
+ Received: from hoyogw.netlab.co.jp (daemon@hoyogw.netlab.co.jp [202.218.249.220])
2
+ by serv1.u-netsurf.ne.jp (8.8.8/3.6W-2.66(99/03/09)) with ESMTP id RAA10692
3
+ for <aamine@dp.u-netsurf.ne.jp>; Thu, 18 Mar 1999 17:35:23 +0900 (JST)
4
+ Received: from hoyogw.netlab.co.jp (matz@localhost [127.0.0.1])
5
+ by hoyogw.netlab.co.jp (8.9.1a+3.1W/3.7W/1.3) with SMTP id RAA13204;
6
+ Thu, 18 Mar 1999 17:21:58 +0900
7
+ Received: from blade.nagaokaut.ac.jp (sinara@blade.nagaokaut.ac.jp [133.44.36.60])
8
+ by hoyogw.netlab.co.jp (8.9.1a+3.1W/3.7W/1.3) with ESMTP id RAA13036
9
+ for <ruby-list@netlab.co.jp>; Thu, 18 Mar 1999 17:20:28 +0900
10
+ Received: (from sinara@localhost)
11
+ by blade.nagaokaut.ac.jp (8.8.8/8.8.8/Debian/GNU) id RAA22078;
12
+ Thu, 18 Mar 1999 17:20:49 +0900
13
+ Posted: Thu, 18 Mar 1999 17:20:49 +0900
14
+ Reply-To: ruby-list@netlab.co.jp
15
+ Subject: [ruby-list:12994] Re: Sieve of Eratosthenes (Re: [ruby-dev:6094])
16
+ Message-Id: <199903180820.RAA22078@blade.nagaokaut.ac.jp>
17
+ In-Reply-To: message of "Wed, 17 Mar 1999 18:42:07 +0900"
18
+ <199903170941.SAA12014@blade.nagaokaut.ac.jp>
19
+ Mime-Version: 1.0
20
+ Content-Type: text/plain; charset = iso-2022-jp
21
+ Content-Transfer-Encoding: 7bit
22
+ Date: Thu, 18 Mar 1999 17:21:54 +0900
23
+ To: ruby-list@netlab.co.jp (ruby mailing list)
24
+ From: (this is comment) local@dom1.dom2
25
+ Subject: this is a test subject
26
+
27
+ line 1
28
+ line 2
29
+ line 3
@@ -0,0 +1,5 @@
1
+ To: Minero Aoki <aamine@harmony.softica.or.jp>
2
+ From: Minero Aoki <aamine@harmony.softica.or.jp>
3
+ Subject: Sendmail test by tmail
4
+
5
+ This is mail sent by tmail.
@@ -0,0 +1,14 @@
1
+ To: これはデコード済 <aamine@dp.u-netsurf.ne.jp>
2
+ From: =?iso-2022-jp?B?GyRCJDMkbCRPJSglcyUzITwlSSQ1JGwkRiQkJD8bKEI=?=
3
+ <myself@softica.or.jp>
4
+ Received: from fromdom.fromdom by bydom.bydom
5
+ via VIAPATH with SMTP id <msgid@tmail> for addr@spec
6
+ ; 23 Mar 1999 22:05:33 +0900
7
+ Mime-Version: 1.0
8
+ Content-Type: text/plain; charset=iso-2022-jp
9
+ Content-Transfer-Encoding: 7bit
10
+ Subject: this is a test subject
11
+
12
+ body line 1
13
+ body line 2
14
+ body line 3
@@ -0,0 +1,27 @@
1
+ Received: from hoyogw.netlab.co.jp (matz@localhost [127.0.0.1])
2
+ by hoyogw.netlab.co.jp (8.9.1a+3.1W/3.7W/1.3)
3
+ with SMTP id RAA13204;
4
+ Thu, 18 Mar 1999 17:21:58 +0900
5
+ Received: from fromdom.fromdom by bydom.bydom
6
+ via VIAPATH with SMTP id <msgid@tmail> for addr@spec;
7
+ 23 Mar 1999 22:05:33 +0900
8
+ Date: Thu, 18 Mar 1999 17:21:54 +0900
9
+ To: ����ϥǥ����ɺ� <"aamine@"@dp.u-netsurf.ne.jp> (Minero Aoki)
10
+ Cc:
11
+ Bcc: =?iso-2022-jp?B?GyRCJDMkbCRPJUclMyE8JUk6URsoQg==?=
12
+ =?iso-2022-jp?B?PGFhbWluZUBkcC51LW5ldHN1cmYubmUuanA+?=
13
+ From: =?iso-2022-jp?B?GyRCJDMkbCRPJSglcyUzITwlSSQ1JGwkRiQkJD8bKEI=?=
14
+ (From comment) (comment2) <myself@softica.or.jp>
15
+ Posted: Thu, 18 Mar 1999 17:20:49 +0900
16
+ Reply-To: ruby-list@netlab.co.jp
17
+ Subject: [ruby-list:12994] Re: Sieve of Eratosthenes
18
+ Message-Id: <199903180820.RAA22078@blade.nagaokaut.ac.jp>
19
+ In-Reply-To: "Wed, 17 Mar 1999 18:42:07 +0900"
20
+ <199903170941.SAA12014@blade.nagaokaut.ac.jp>
21
+ Mime-Version: 1.0
22
+ Content-Type: text/plain; charset=iso-2022-jp
23
+ Content-Transfer-Encoding: 7bit
24
+
25
+ line 1
26
+ line 2
27
+ line 3
@@ -0,0 +1,33 @@
1
+ #
2
+ # extract-attachments.rb -- Extracts attachment(s) from the message.
3
+ #
4
+ # Usage: ruby extract-attachments.rb mail mail...
5
+ #
6
+
7
+ require 'tmail'
8
+
9
+ def main
10
+ idx = 1
11
+ ARGV.each do |fname|
12
+ TMail::Mail.load(fname).parts.each do |m|
13
+ m.base64_decode
14
+ File.open("#{idx}.#{ext(m)}", 'w') {|f|
15
+ f.write m.body
16
+ }
17
+ idx += 1
18
+ end
19
+ end
20
+ end
21
+
22
+ CTYPE_TO_EXT = {
23
+ 'image/jpeg' => 'jpeg',
24
+ 'image/gif' => 'gif',
25
+ 'image/png' => 'png',
26
+ 'image/tiff' => 'tiff'
27
+ }
28
+
29
+ def ext( mail )
30
+ CTYPE_TO_EXT[mail.content_type] || 'txt'
31
+ end
32
+
33
+ main
@@ -0,0 +1,26 @@
1
+ #
2
+ # checking mail From: header
3
+ #
4
+
5
+ require 'tmail'
6
+
7
+ unless ARGV[0] then
8
+ $stderr.puts "usage: ruby fromcheck.rb <mhdir>"
9
+ exit 1
10
+ end
11
+
12
+ table = {} # from-addr-spec => [count, friendly-from]
13
+ ld = TMail::MhLoader.new( ARGV[0] )
14
+ ld.each_port do |port|
15
+ mail = TMail::Mail.new( port )
16
+ addr, = mail.from_addrs
17
+ if addr then
18
+ (table[addr.spec] ||= [0, mail.friendly_from])[0] += 1
19
+ end
20
+ end
21
+
22
+ table.to_a.sort {|a,b|
23
+ b[1][0] <=> a[1][0]
24
+ }.each_with_index do |(spec,(n,from)), i|
25
+ printf "%3d %-33s %d\n", i+1, from, n
26
+ end
@@ -0,0 +1,26 @@
1
+ #
2
+ # MIME multipart parsing test
3
+ #
4
+
5
+ require 'tmail'
6
+
7
+ mail = TMail::Mail.load( ARGV[0] || 'data/multipart' )
8
+
9
+ puts '========= preamble =============='
10
+ puts mail.body
11
+ puts
12
+
13
+ puts '========== parts ================'
14
+ mail.parts.each_with_index do |i,idx|
15
+ puts "<#{idx+1}>"
16
+ puts i
17
+ puts
18
+ end
19
+
20
+ puts '========= epilogue =============='
21
+ puts mail.epilogue
22
+ puts
23
+
24
+ puts "========= re-struct ============="
25
+ puts mail.decoded
26
+ puts
@@ -0,0 +1,68 @@
1
+ #
2
+ # parser benchmark
3
+ #
4
+
5
+ require 'tmail'
6
+
7
+
8
+ if ARGV.empty? then
9
+ $stderr.puts "usage: #{$0} <mhdir> <mhdir>..."
10
+ exit 0
11
+ end
12
+ ARGV.each do |dname|
13
+ unless File.directory? dname then
14
+ $stderr.puts "not directory: #{dname}"
15
+ exit 1
16
+ end
17
+ end
18
+
19
+ $stdout.sync = true
20
+
21
+ $count = 0
22
+ $failnum = 0
23
+ $dirfail = 0
24
+ $fieldname = ''
25
+ $dirname = ''
26
+ $port = nil
27
+
28
+ begin
29
+ ARGV.each do |dirname|
30
+ $dirname = dirname
31
+
32
+ TMail::MhLoader.new( dirname ).each do |port|
33
+ begin
34
+ t = TMail::Mail.new( port )
35
+ $port = port
36
+
37
+ t.each_header do |key, field|
38
+ $fieldname = key
39
+ next if /received/i === key
40
+ if ::TMail::StructH === field then
41
+ field.instance_eval { parse unless @parsed }
42
+ end
43
+ end
44
+ rescue TMail::SyntaxError
45
+ $stderr.puts "fail in #{$count+1}, field #{$fieldname}"
46
+ $stderr.puts $!.to_s
47
+ $failnum += 1
48
+ $dirfail += 1
49
+
50
+ if $failnum % 10 == 0 then
51
+ puts 'fail = ' + $failnum.to_s
52
+ #raise
53
+ end
54
+ end
55
+
56
+ $count += 1
57
+ puts "end #{$count}" if $count % 50 == 0
58
+ end
59
+
60
+ puts "directory #{dirname} end, fail=#{$dirfail}"
61
+ $dirfail = 0
62
+ end
63
+ rescue
64
+ puts "at #{$port.inspect}, non ParseError raised"
65
+ raise
66
+ end
67
+
68
+ puts "parse #{$count} files, fail=#{$failnum}"
@@ -0,0 +1,19 @@
1
+ #
2
+ # parser test
3
+ #
4
+
5
+ require 'tmail'
6
+
7
+ puts "testing parser --------------------------------"
8
+ puts
9
+
10
+ TMail::Mail.load( 'data/normal' ).each_header do |key, field|
11
+ if field.respond_to? :parse, true then
12
+ field.instance_eval {
13
+ parse
14
+ @written = true
15
+ }
16
+ end
17
+ printf "%s ok\n", field.name
18
+ # puts field.decoded
19
+ end
@@ -0,0 +1,94 @@
1
+ #
2
+ # sendmail.rb
3
+ #
4
+
5
+ require 'tmail'
6
+ require 'net/smtp'
7
+ require 'nkf'
8
+ require 'etc'
9
+ require 'socket'
10
+ require 'getopts'
11
+
12
+
13
+ def usage( status, msg = nil )
14
+ output = (status == 0 ? $stdout : $stderr)
15
+ output.puts msg if msg
16
+ output.print(<<EOS)
17
+ Usage: cat msg | #{File.basename $0} [-j|--ja] [-s <subject>] [-f <from>] <to>
18
+
19
+ -h,--host=addr SMTP server address. (default=localhost)
20
+ -s,--subject=sbj subject of the message. (default=(none))
21
+ -f,--from=from from address.
22
+ -j,--ja handle japanese message. (default=off)
23
+
24
+ EOS
25
+ exit status
26
+ end
27
+
28
+ def main
29
+ getopts('j', 'ja', 'h:', 'host:',
30
+ 's:', 'subject:', 'f:', 'from:',
31
+ 'help') or usage(1)
32
+
33
+ smtphost = $OPT_host || $OPT_h || 'localhost'
34
+ subject = $OPT_subject || $OPT_s
35
+ from = $OPT_from || $OPT_f || guess_from_address()
36
+ usage(1, 'Sender address not given') unless from
37
+ to = ARGV
38
+ usage(1, 'Receipt address(es) not given') if to.empty?
39
+ ja_locale = $OPT_ja || $OPT_j
40
+
41
+ send_mail smtphost, setup_mail(from, to, subject, $stdin.read, ja_locale)
42
+ end
43
+
44
+ def setup_mail( from, to, subject, body, ja_locale )
45
+ mail = TMail::Mail.new
46
+ mail.date = Time.now
47
+ mail.from = from
48
+ mail.to = to
49
+ mail.subject = subject if subject
50
+ mail.mime_version = '1.0'
51
+ if ja_locale
52
+ mail.body = NKF.nkf('-j', body)
53
+ mail.set_content_type 'text', 'plain', 'charset' => 'iso-2022-jp'
54
+ else
55
+ mail.body = body
56
+ mail.set_content_type 'text', 'plain'
57
+ end
58
+ mail
59
+ end
60
+
61
+ def send_mail( host, mail )
62
+ msg = mail.encoded
63
+ $stderr.print msg if $DEBUG
64
+
65
+ smtp = Net::SMTP.new(host, 25)
66
+ smtp.set_debug_output $stderr if $DEBUG
67
+ smtp.start {
68
+ smtp.send_mail msg, mail.from_address, mail.destinations
69
+ }
70
+ end
71
+
72
+ def guess_from_address
73
+ user = getlogin()
74
+ unless user
75
+ $stderr.puts 'cannot get user account; abort.'
76
+ exit 1
77
+ end
78
+ if domain = (Socket.gethostname || ENV['HOSTNAME'] || ENV['HOST'])
79
+ user + '@' + domain
80
+ else
81
+ user
82
+ end
83
+ end
84
+
85
+ def getlogin
86
+ begin
87
+ require 'etc'
88
+ Etc.getlogin
89
+ rescue LoadError
90
+ ENV['LOGNAME'] || ENV['USER']
91
+ end
92
+ end
93
+
94
+ main