tmail 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
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