tmail 1.2.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/CHANGES +11 -0
  2. data/NOTES +48 -38
  3. data/README +3 -2
  4. data/Rakefile +11 -0
  5. data/ext/Makefile +8 -8
  6. data/ext/{mailscanner → tmailscanner}/tmail/MANIFEST +1 -1
  7. data/ext/tmailscanner/tmail/depend +1 -0
  8. data/ext/{mailscanner → tmailscanner}/tmail/extconf.rb +1 -1
  9. data/ext/{mailscanner/tmail/mailscanner.c → tmailscanner/tmail/tmailscanner.c} +10 -10
  10. data/lib/tmail/address.rb +9 -1
  11. data/lib/tmail/encode.rb +1 -0
  12. data/lib/tmail/header.rb +34 -2
  13. data/lib/tmail/mailbox.rb +3 -3
  14. data/lib/tmail/quoting.rb +0 -24
  15. data/lib/tmail/scanner.rb +4 -4
  16. data/lib/tmail/scanner_r.rb +1 -1
  17. data/lib/tmail/utils.rb +2 -3
  18. data/lib/tmail/version.rb +1 -1
  19. data/log/ChangeLog.txt +22 -0
  20. data/log/History.txt +1 -1
  21. data/meta/MANIFEST +18 -8
  22. data/{script → meta}/config.yaml +1 -1
  23. data/meta/tmail.roll +3 -0
  24. data/script/clobber/distclean +1 -1
  25. data/script/compile +2 -2
  26. data/script/pack/gem +93 -0
  27. data/script/pack/tgz +41 -0
  28. data/script/pack/zip +41 -0
  29. data/script/prepare +6 -1
  30. data/script/publish +2 -2
  31. data/script/rdoc +42 -0
  32. data/script/release +1 -3
  33. data/script/stamp +33 -0
  34. data/script/test +1 -1
  35. data/test/fixtures/mailbox +13 -0
  36. data/test/fixtures/mailbox_without_any_from_or_sender +10 -0
  37. data/test/fixtures/mailbox_without_from +11 -0
  38. data/test/fixtures/mailbox_without_return_path +12 -0
  39. data/test/fixtures/raw_email11 +2 -2
  40. data/test/fixtures/raw_email_with_bad_date +5 -5
  41. data/test/test_address.rb +32 -2
  42. data/test/test_attachments.rb +15 -0
  43. data/test/test_encode.rb +54 -52
  44. data/test/test_header.rb +57 -0
  45. data/test/test_helper.rb +1 -0
  46. data/test/test_mail.rb +49 -1
  47. data/test/test_mbox.rb +21 -0
  48. data/test/test_quote.rb +71 -0
  49. metadata +173 -153
  50. data/ext/mailscanner/tmail/depend +0 -1
  51. data/meta/ROLLRC +0 -3
data/CHANGES CHANGED
@@ -1,3 +1,14 @@
1
+ = TMail 1.2.1 / 2008-01-11
2
+
3
+ * More documentation (Mikel)
4
+ * Added 15 test cases from the Rails ActionMailer to TMail
5
+ * Changed mailscanner to tmailscanner (mailscanner is copyrighted)
6
+ * Closed Bug - Handled quote boundary being gready on content-type header (M. Mondragon)
7
+ * Closed #16025 - Fixed scanner.rb so it passes same tests as scanner.c
8
+ * Closed #16283 - Handled incorrect decoding of attachments (M. Aoki - garyo)
9
+ * Closed #16899 - HeaderField.new_from_port and added test cases to cover this code (Maarten O.)
10
+ * Closed #16900 - UNIXMbox.fromaddr missing port param and does not return Envelope Sender (Maarten O.)
11
+
1
12
  = TMail 1.2.0 / 2007-11-29
2
13
 
3
14
  * Extensive documentation work. (mikel)
data/NOTES CHANGED
@@ -1,4 +1,4 @@
1
- [ANN] TMail 1.2.0
1
+ [ANN] TMail 1.2.1 - 11 Jan 2008
2
2
 
3
3
  TMail is The Mail Handling Library for Ruby!
4
4
 
@@ -20,49 +20,59 @@ http://tmail.rubyforge.org/
20
20
 
21
21
  Release Summary:
22
22
  ------------------
23
- New release handles two tickets in the TMail
23
+ New release handles five tickets in the TMail
24
24
  tracker as well as a lot more documentation and
25
- removes an unnecessary c-library.
25
+ renames a library to handle copyright concerns.
26
+
27
+ Additionally added 25 more test cases to the library
28
+ to handle the above tickets.
29
+
30
+ This should be a drop in replacement for existing
31
+ TMail installations.
26
32
 
27
33
 
28
34
  Release Update Details:
29
35
  -------------------------
30
36
 
31
- Closed 15445 - TMail::Mail#create_forward now returns
32
- a new Mail object that has the original mail as an
33
- encoded 7 bit multipart attachment. Also moved
34
- create_forward and create_reply from tmail/net
35
- into tmail/interface as it makes more sense to have
36
- it there.
37
-
38
- Closed 15643 - TMail::Mail#reply_addresses was
39
- returning an empty array if reply_to was set to nil
40
- (ie, the header field existed but was empty) instead
41
- of returning the from address or default.
42
-
43
- Removed base64.c after doing profiling on several
44
- platforms and finding out that the Ruby inbuilt
45
- version is just as fast (varies per platform but
46
- all in all about the same speed.)
47
-
48
- Renamed the Scanner_C extension to MailScanner.
49
-
50
- New release adds extensive new documentation to
51
- mainly the TMail::Mail class, approximately 500
52
- lines of examples have been included in the RDoc.
53
-
54
- Added a default value to TMail::Mail#sender method
55
- to allow arbitrary defaults to be passed into the
56
- method in alignment with all the other mail interface
57
- methods.
58
-
59
- Made base64_decode and base64_encode into ! versions
60
- as they are destructive on the mail body (encodes the
61
- body to base64 or decodes it), made aliases for
62
- base64_decode and base64_encode to point back to the
63
- bang versions. Doing this with a view to change
64
- base64_encode to a non destructive version
65
- (returns the encoded body) in future versions.
37
+ Closed #16899 - HeaderField.new_from_port and added test
38
+ cases to cover this code. Also changed behaviour of
39
+ HeaderField.new_from_port to return nil if it does not
40
+ find a matching header in the port provided. Extended
41
+ UNIXMbox.fromaddr to also search for EnvelopeSender and
42
+ also made it a public method, not private - Thanks to
43
+ Maarten O. for alerting these bugs
44
+
45
+ Closed #16900 - UNIXMbox.fromaddr missing port param and
46
+ does not return Envelope Sender. This report was
47
+ initially to correct typo on "Regep" to "Regexp". Also
48
+ added test cases to cover this class method. Also added
49
+ ability to scan for the EnvelopeSender explictly as it
50
+ would not come up on searching for "From" due to Regexp
51
+ confilct with From: (with the colon). Thanks to Maarten
52
+ O. for reporting this.
53
+
54
+ Closed 16025 - TMail scanner.rb would not parse ATOM
55
+ chars correctly making it fail tests where the C version
56
+ passed them. Fixed this by updating the Scanner.rb
57
+ version to be in step with the C version (there was an
58
+ extra @ symbol in the ATOM CHARS definition that was not
59
+ in the C version.) (mikel)
60
+
61
+ Closed 16283 - TMail would not decode correctly due to
62
+ bug in text-utils - put in previous patch from old tmail
63
+ trunk version. Thanks to garyo for spotting this.
64
+
65
+ Closed Bug - Handled quote boundary being gready on
66
+ content-type header fields (M. Mondragon)
67
+
68
+ Changed the name of mailscanner to tmailscanner to handle
69
+ a copyright issue. MailScanner is a copyrighted name.
70
+
71
+ Added about 15 test cases from the Rails community. Added
72
+ failing test case for an unquoted @ char in the From
73
+ header field. Need to check fully if this is needed or
74
+ not, but it is there anyway - to be resolved. I have
75
+ emailed 822 mailing list to check this out.
66
76
 
67
77
  See the changelog for previous changes.
68
78
 
data/README CHANGED
@@ -28,6 +28,8 @@ I really welcome any examples of Emails that "didn't work" with TMail so I can u
28
28
 
29
29
  TMail is very easy to use. You simply require the library and then pass a raw email text message into the TMail::Mail.parse method. This returns a TMail::Mail object which you can now query and run methods against to modify, inspect or add to the Email.
30
30
 
31
+ You can find almost all of the methods that you will use to talk to and update a TMail instance in the TMail::Mail class. I am constantly updating this code, with comments, added a fair bit and have a lot more to go!.
32
+
31
33
  === Short Version:
32
34
 
33
35
  irb(main):001:0> require 'tmail'
@@ -123,8 +125,7 @@ You can just call to_s on any email to have it serialized out as a single string
123
125
 
124
126
  == REQUIREMENTS:
125
127
 
126
- * Ruby 1.6 or later
127
- * C compiler if you want the Ruby extensions for Scanner and Base64
128
+ * C compiler if you want the Ruby extension for Scanner
128
129
  * Ruby 1.8 or later
129
130
 
130
131
  == INSTALLATION:
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+
5
+ # Run the unit tests
6
+ Rake::TestTask.new { |t|
7
+ t.libs << "test"
8
+ t.pattern = 'test/test_*.rb'
9
+ t.verbose = true
10
+ t.warning = false
11
+ }
@@ -2,19 +2,19 @@
2
2
  # ext/tmail/Makefile
3
3
  #
4
4
 
5
- .PHONY: mailscanner clean distclean
5
+ .PHONY: tmailscanner clean distclean
6
6
 
7
- all: mailscanner
7
+ all: tmailscanner
8
8
 
9
- mailscanner: mailscanner/tmail/Makefile
10
- cd mailscanner/tmail; $(MAKE)
9
+ tmailscanner: tmailscanner/tmail/Makefile
10
+ cd tmailscanner/tmail; $(MAKE)
11
11
 
12
- mailscanner/tmail/Makefile: mailscanner/tmail/extconf.rb
13
- cd mailscanner/tmail; ruby extconf.rb
12
+ tmailscanner/tmail/Makefile: tmailscanner/tmail/extconf.rb
13
+ cd tmailscanner/tmail; ruby extconf.rb
14
14
 
15
15
  clean:
16
- cd mailscanner/tmail; $(MAKE) clean
16
+ cd tmailscanner/tmail; $(MAKE) clean
17
17
 
18
18
  distclean:
19
- cd mailscanner/tmail; $(MAKE) distclean
19
+ cd tmailscanner/tmail; $(MAKE) distclean
20
20
 
@@ -1,4 +1,4 @@
1
1
  MANIFEST
2
- mailscanner.c
2
+ tmailscanner.c
3
3
  extconf.rb
4
4
  depend
@@ -0,0 +1 @@
1
+ tmailscanner.o: tmailscanner.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h Makefile
@@ -1,7 +1,7 @@
1
1
  require 'mkmf'
2
2
  require 'rbconfig'
3
3
 
4
- extension_name = 'mailscanner'
4
+ extension_name = 'tmailscanner'
5
5
 
6
6
  arch = Config::CONFIG['sitearch']
7
7
 
@@ -1,6 +1,6 @@
1
1
  /*
2
2
 
3
- mailscanner.c
3
+ tmailscanner.c
4
4
 
5
5
  Copyright (c) 1998-2007 Minero Aoki
6
6
 
@@ -21,7 +21,7 @@
21
21
 
22
22
  #define TMAIL_VERSION "0.11.0"
23
23
 
24
- static VALUE MailScanner;
24
+ static VALUE TMailScanner;
25
25
  static VALUE ScanError;
26
26
 
27
27
  struct scanner
@@ -95,7 +95,7 @@ mails_s_new(klass, str, ident, cmt)
95
95
  sc->comments = cmt;
96
96
  }
97
97
 
98
- return Data_Wrap_Struct(MailScanner, 0, mails_free, sc);
98
+ return Data_Wrap_Struct(TMailScanner, 0, mails_free, sc);
99
99
  }
100
100
 
101
101
  /*
@@ -538,7 +538,7 @@ cstr2symbol(str)
538
538
  }
539
539
 
540
540
  void
541
- Init_mailscanner()
541
+ Init_tmailscanner()
542
542
  {
543
543
  VALUE TMail;
544
544
  VALUE tmp;
@@ -549,16 +549,16 @@ Init_mailscanner()
549
549
  else {
550
550
  TMail = rb_define_module("TMail");
551
551
  }
552
- MailScanner = rb_define_class_under(TMail, "MailScanner", rb_cObject);
552
+ TMailScanner = rb_define_class_under(TMail, "TMailScanner", rb_cObject);
553
553
 
554
554
  tmp = rb_str_new2(TMAIL_VERSION);
555
555
  rb_obj_freeze(tmp);
556
- rb_define_const(MailScanner, "Version", tmp);
556
+ rb_define_const(TMailScanner, "Version", tmp);
557
557
 
558
- rb_define_singleton_method(MailScanner, "new", mails_s_new, 3);
559
- rb_define_method(MailScanner, "scan", mails_scan, 0);
560
- rb_define_method(MailScanner, "debug", mails_debug_get, 0);
561
- rb_define_method(MailScanner, "debug=", mails_debug_set, 1);
558
+ rb_define_singleton_method(TMailScanner, "new", mails_s_new, 3);
559
+ rb_define_method(TMailScanner, "scan", mails_scan, 0);
560
+ rb_define_method(TMailScanner, "debug", mails_debug_get, 0);
561
+ rb_define_method(TMailScanner, "debug=", mails_debug_set, 1);
562
562
 
563
563
  if (rb_const_defined(TMail, rb_intern("SyntaxError"))) {
564
564
  ScanError = rb_const_get(rb_cObject, rb_intern("SyntaxError"));
@@ -54,8 +54,16 @@ module TMail
54
54
  raise SyntaxError, 'empty word in domain' if s.empty?
55
55
  end
56
56
  end
57
+
58
+ # This is to catch an unquoted "@" symbol in the local part of the
59
+ # address. Handles addresses like <"@"@me.com> and makes sure they
60
+ # stay like <"@"@me.com> (previously were becomming <@@me.com>)
61
+ if local.to_s == '@' || local.to_s =~ /\A[^"].*?@.*?[^"]\Z/
62
+ @local = "\"#{local.to_s}\""
63
+ else
64
+ @local = local
65
+ end
57
66
 
58
- @local = local
59
67
  @domain = domain
60
68
  @name = nil
61
69
  @routes = []
@@ -195,6 +195,7 @@ module TMail
195
195
  @f = StrategyInterface.create_dest(dest)
196
196
  @opt = OPTIONS[$KCODE]
197
197
  @eol = eol
198
+ @folded = false
198
199
  @preserve_quotes = true
199
200
  reset
200
201
  end
@@ -54,8 +54,40 @@ module TMail
54
54
  klass.newobj body, conf
55
55
  end
56
56
 
57
+ # Returns a HeaderField object matching the header you specify in the "name" param.
58
+ # Requires an initialized TMail::Port to be passed in.
59
+ #
60
+ # The method searches the header of the Port you pass into it to find a match on
61
+ # the header line you pass. Once a match is found, it will unwrap the matching line
62
+ # as needed to return an initialized HeaderField object.
63
+ #
64
+ # If you want to get the Envelope sender of the email object, pass in "EnvelopeSender",
65
+ # if you want the From address of the email itself, pass in 'From'.
66
+ #
67
+ # This is because a mailbox doesn't have the : after the From that designates the
68
+ # beginning of the envelope sender (which can be different to the from address of
69
+ # the emial)
70
+ #
71
+ # Other fields can be passed as normal, "Reply-To", "Received" etc.
72
+ #
73
+ # Note: Change of behaviour in 1.2.1 => returns nil if it does not find the specified
74
+ # header field, otherwise returns an instantiated object of the correct header class
75
+ #
76
+ # For example:
77
+ # port = TMail::FilePort.new("/test/fixtures/raw_email_simple")
78
+ # h = TMail::HeaderField.new_from_port(port, "From")
79
+ # h.addrs.to_s #=> "Mikel Lindsaar <mikel@nowhere.com>"
80
+ # h = TMail::HeaderField.new_from_port(port, "EvelopeSender")
81
+ # h.addrs.to_s #=> "mike@anotherplace.com.au"
82
+ # h = TMail::HeaderField.new_from_port(port, "SomeWeirdHeaderField")
83
+ # h #=> nil
57
84
  def new_from_port( port, name, conf = DEFAULT_CONFIG )
58
- re = Regep.new('\A(' + Regexp.quote(name) + '):', 'i')
85
+ if name == "EnvelopeSender"
86
+ name = "From"
87
+ re = Regexp.new('\A(From) ', 'i')
88
+ else
89
+ re = Regexp.new('\A(' + Regexp.quote(name) + '):', 'i')
90
+ end
59
91
  str = nil
60
92
  port.ropen {|f|
61
93
  f.each do |line|
@@ -66,7 +98,7 @@ module TMail
66
98
  end
67
99
  end
68
100
  }
69
- new(name, str, Config.to_config(conf))
101
+ new(name, str, Config.to_config(conf)) if str
70
102
  end
71
103
 
72
104
  def internal_new( name, conf )
@@ -213,13 +213,13 @@ module TMail
213
213
  fromaddr(), TextUtils.time2str(File.mtime(port.filename))
214
214
  end
215
215
 
216
- def UNIXMbox.fromaddr
216
+ def UNIXMbox.fromaddr(port)
217
217
  h = HeaderField.new_from_port(port, 'Return-Path') ||
218
- HeaderField.new_from_port(port, 'From') or return 'nobody'
218
+ HeaderField.new_from_port(port, 'From') ||
219
+ HeaderField.new_from_port(port, 'EnvelopeSender') or return 'nobody'
219
220
  a = h.addrs[0] or return 'nobody'
220
221
  a.spec
221
222
  end
222
- private_class_method :fromaddr
223
223
 
224
224
  def close
225
225
  return if @closed
@@ -116,27 +116,3 @@ module TMail
116
116
  end
117
117
  end
118
118
  end
119
-
120
- if __FILE__ == $0
121
- require 'test/unit'
122
-
123
- class TC_Unquoter < Test::Unit::TestCase
124
- def test_unquote_quoted_printable
125
- a ="=?ISO-8859-1?Q?[166417]_Bekr=E6ftelse_fra_Rejsefeber?="
126
- b = TMail::Unquoter.unquote_and_convert_to(a, 'utf-8')
127
- assert_equal "[166417] Bekr\303\246ftelse fra Rejsefeber", b
128
- end
129
-
130
- def test_unquote_base64
131
- a ="=?ISO-8859-1?B?WzE2NjQxN10gQmVrcuZmdGVsc2UgZnJhIFJlanNlZmViZXI=?="
132
- b = TMail::Unquoter.unquote_and_convert_to(a, 'utf-8')
133
- assert_equal "[166417] Bekr\303\246ftelse fra Rejsefeber", b
134
- end
135
-
136
- def test_unquote_without_charset
137
- a ="[166417]_Bekr=E6ftelse_fra_Rejsefeber"
138
- b = TMail::Unquoter.unquote_and_convert_to(a, 'utf-8')
139
- assert_equal "[166417]_Bekr=E6ftelse_fra_Rejsefeber", b
140
- end
141
- end
142
- end
@@ -34,15 +34,15 @@ require 'tmail/utils'
34
34
  require 'tmail/config'
35
35
 
36
36
  module TMail
37
- # NOTE: It woiuld be nice if these two libs could boith be called "mailscanner", and
37
+ # NOTE: It woiuld be nice if these two libs could boith be called "tmailscanner", and
38
38
  # the native extension would have precedence. However RubyGems boffs that up b/c
39
39
  # it does not gaurantee load_path order.
40
40
  begin
41
41
  raise LoadError, 'Turned off native extentions by user choice' if ENV['NORUBYEXT']
42
- require('tmail/mailscanner') # c extension
43
- Scanner = MailScanner
42
+ require('tmail/tmailscanner') # c extension
43
+ Scanner = TMailScanner
44
44
  rescue LoadError
45
45
  require 'tmail/scanner_r'
46
- Scanner = MailScanner
46
+ Scanner = TMailScanner
47
47
  end
48
48
  end
@@ -31,7 +31,7 @@ require 'tmail/config'
31
31
 
32
32
  module TMail
33
33
 
34
- class MailScanner
34
+ class TMailScanner
35
35
 
36
36
  Version = '0.11.0'
37
37
  Version.freeze
@@ -248,8 +248,7 @@ module TMail
248
248
  def decode_RFC2231( str )
249
249
  m = RFC2231_ENCODED.match(str) or return str
250
250
  begin
251
- NKF.nkf(NKF_FLAGS[$KCODE],
252
- m.post_match.gsub(/%[\da-f]{2}/in) {|s| s[1,2].hex.chr })
251
+ to_kcode(m.post_match.gsub(/%[\da-f]{2}/in) {|s| s[1,2].hex.chr })
253
252
  rescue
254
253
  m.post_match.gsub(/%[\da-f]{2}/in, "")
255
254
  end
@@ -263,7 +262,7 @@ module TMail
263
262
  preamble = $1
264
263
  remainder = $2
265
264
  if remainder =~ /;/
266
- remainder =~ /^(.*)(;.*)$/m
265
+ remainder =~ /^(.*?)(;.*)$/m
267
266
  boundary_text = $1
268
267
  post = $2.chomp
269
268
  else
@@ -31,7 +31,7 @@ module TMail #:nodoc:
31
31
  module VERSION #:nodoc:
32
32
  MAJOR = 1
33
33
  MINOR = 2
34
- TINY = 0
34
+ TINY = 1
35
35
 
36
36
  STRING = [MAJOR, MINOR, TINY].join('.')
37
37
  end
@@ -1,7 +1,29 @@
1
+ == Thu Jan 10 15:09:02 GMT 2008 Mikel Lindsaar <raasdnil@gmail.com>
2
+
3
+ * Closed #16899 - HeaderField.new_from_port and added test cases to cover this code. Also changed behaviour of HeaderField.new_from_port to return nil if it does not find a matching header in the port provided. Extended UNIXMbox.fromaddr to also search for EnvelopeSender and also made it a public method, not private - Thanks to Maarten O. for alerting these bugs
4
+
5
+ * Closed #16900 - UNIXMbox.fromaddr missing port param and does not return Envelope Sender. This report was initially to correct typo on "Regep" to "Regexp". Also added test cases to cover this class method. Also added ability to scan for the EnvelopeSender explictly as it would not come up on searching for "From" due to Regexp confilct with From: (with the colon). Thanks to Maarten O. for reporting this.
6
+
7
+ == Thu Dec 25 23:10:16 GMT 2007 Mikel Lindsaar <raasdnil@gmail.com>
8
+
9
+ * Closed Bug - Handled quote boundary being gready on content-type header fields (M. Mondragon)
10
+
11
+ == Thu Dec 25 20:10:46 GMT 2007 Mikel Lindsaar <raasdnil@gmail.com>
12
+
13
+ * Change the name of mailscanner to tmailscanner to handle a copyright issue. MailScanner is a copyrighted name.
14
+
15
+ == Thu Dec 02 11:11:36 GMT 2008 Mikel Lindsaar <raasdnil@gmail.com>
16
+
17
+ * Added about 15 test cases from the Rails community. Added failing test case for an unquoted @ char in the From header field. Need to check fully if this is needed or not, but it is there anyway - to be resolved. I have emailed 822 mailing list to check this out.
18
+
1
19
  == Fri Nov 30 08:04:09 GMT 2007 Mikel Lindsaar <raasdnil@gmail.com>
2
20
 
3
21
  * Closed 16025 - TMail scanner.rb would not parse ATOM chars correctly making it fail tests where the C version passed them. Fixed this by updating the Scanner.rb version to be in step with the C version (there was an extra @ symbol in the ATOM CHARS definition that was not in the C version.) (mikel)
4
22
 
23
+ == Fri Nov 25 05:41:15 GMT 2007 Mikel Lindsaar <raasdnil@gmail.com>
24
+
25
+ * Closed 16283 - TMail would not decode correctly due to bug in text-utils - put in previous patch from old tmail trunk version. Thanks to garyo for spotting this.
26
+
5
27
  == Mon Nov 19 23:15:29 GMT 2007 Mikel Lindsaar <raasdnil@gmail.com>
6
28
 
7
29
  * Added about 500 lines of documentation to the interface.rb file.