tmail 1.2.3.1 → 1.2.6
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.
- data/README +10 -0
- data/ext/tmailscanner/tmail/tmailscanner.c +39 -8
- data/lib/tmail.rb +1 -0
- data/lib/tmail/address.rb +6 -40
- data/lib/tmail/attachments.rb +41 -22
- data/lib/tmail/encode.rb +9 -0
- data/lib/tmail/header.rb +5 -3
- data/lib/tmail/interface.rb +40 -3
- data/lib/tmail/mail.rb +3 -3
- data/lib/tmail/mailbox.rb +3 -2
- data/lib/tmail/net.rb +3 -1
- data/lib/tmail/parser.rb +204 -620
- data/lib/tmail/parser.y +38 -3
- data/lib/tmail/quoting.rb +38 -1
- data/lib/tmail/utils.rb +28 -4
- data/lib/tmail/vendor/rchardet-1.3/COPYING +504 -0
- data/lib/tmail/vendor/rchardet-1.3/README +12 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet.rb +67 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/big5freq.rb +927 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/big5prober.rb +42 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/chardistribution.rb +237 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/charsetgroupprober.rb +112 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/charsetprober.rb +75 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/codingstatemachine.rb +64 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/constants.rb +42 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/escprober.rb +90 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/escsm.rb +244 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/eucjpprober.rb +88 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/euckrfreq.rb +596 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/euckrprober.rb +42 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/euctwfreq.rb +430 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/euctwprober.rb +42 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/gb2312freq.rb +474 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/gb2312prober.rb +42 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/hebrewprober.rb +289 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/jisfreq.rb +570 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/jpcntx.rb +229 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/langbulgarianmodel.rb +229 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/langcyrillicmodel.rb +330 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/langgreekmodel.rb +227 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/langhebrewmodel.rb +202 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/langhungarianmodel.rb +226 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/langthaimodel.rb +201 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/latin1prober.rb +147 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/mbcharsetprober.rb +89 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/mbcsgroupprober.rb +47 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/mbcssm.rb +542 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/sbcharsetprober.rb +124 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/sbcsgroupprober.rb +58 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/sjisprober.rb +88 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/universaldetector.rb +166 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/utf8prober.rb +87 -0
- data/lib/tmail/version.rb +1 -1
- data/setup.rb +2 -2
- data/test/fixtures/apple_unquoted_content_type +44 -0
- data/test/fixtures/inline_attachment.txt +2095 -0
- data/test/fixtures/iso_8859_1_email_without_encoding_and_message_id.txt +16 -0
- data/test/fixtures/mailbox.zip +0 -0
- data/test/fixtures/marked_as_iso_8859_1_but_it_is_utf_8.txt +33 -0
- data/test/fixtures/marked_as_utf_8_but_it_is_iso_8859_1.txt +56 -0
- data/test/fixtures/raw_email_bad_time +62 -0
- data/test/fixtures/raw_email_double_at_in_header +14 -0
- data/test/fixtures/raw_email_only_attachment +17 -0
- data/test/fixtures/raw_email_string_in_date_field +17 -0
- data/test/fixtures/raw_email_trailing_dot +21 -0
- data/test/fixtures/raw_email_with_quoted_attachment_filename +60 -0
- data/test/fixtures/raw_email_with_wrong_splitted_multibyte_encoded_word_subject +15 -0
- data/test/fixtures/the_only_part_is_a_word_document.txt +425 -0
- data/test/fixtures/unquoted_filename_in_attachment +177 -0
- data/test/test_address.rb +114 -92
- data/test/test_attachments.rb +84 -1
- data/test/test_encode.rb +54 -0
- data/test/test_header.rb +60 -2
- data/test/test_mail.rb +22 -15
- data/test/test_mbox.rb +12 -3
- data/test/test_port.rb +13 -9
- data/test/test_quote.rb +9 -0
- data/tmail.gemspec +34 -0
- metadata +68 -167
- data/MANIFEST +0 -191
- data/log/BugTrackingLog.txt +0 -1231
- data/log/Changelog.txt +0 -534
- data/log/Fixme.txt +0 -6
- data/log/Testlog.txt +0 -2340
- data/log/Todo.txt +0 -30
- data/log/fixme.rdoc +0 -6
- data/meta/MANIFEST +0 -128
- data/meta/VERSION +0 -1
- data/meta/project.yaml +0 -30
- data/meta/unixname +0 -1
- data/sample/bench_base64.rb +0 -48
- data/sample/data/multipart +0 -23
- data/sample/data/normal +0 -29
- data/sample/data/sendtest +0 -5
- data/sample/data/simple +0 -14
- data/sample/data/test +0 -27
- data/sample/extract-attachements.rb +0 -33
- data/sample/from-check.rb +0 -26
- data/sample/multipart.rb +0 -26
- data/sample/parse-bench.rb +0 -68
- data/sample/parse-test.rb +0 -19
- data/sample/sendmail.rb +0 -94
- data/site/contributing/index.html +0 -183
- data/site/css/clean.css +0 -27
- data/site/css/layout.css +0 -31
- data/site/css/style.css +0 -60
- data/site/download/index.html +0 -61
- data/site/img/envelope.jpg +0 -0
- data/site/img/mailman.gif +0 -0
- data/site/img/stamp-sm.jpg +0 -0
- data/site/img/stamp.jpg +0 -0
- data/site/img/stampborder.jpg +0 -0
- data/site/img/tfire.jpg +0 -0
- data/site/img/tmail.png +0 -0
- data/site/index.html +0 -270
- data/site/js/jquery.js +0 -31
- data/site/log/Changelog.xsl +0 -33
- data/site/log/changelog.xml +0 -1677
- data/site/outdated/BUGS +0 -3
- data/site/outdated/DEPENDS +0 -1
- data/site/outdated/Incompatibilities +0 -89
- data/site/outdated/Incompatibilities.ja +0 -102
- data/site/outdated/NEWS +0 -9
- data/site/outdated/README.ja +0 -73
- data/site/outdated/doc.ja/address.html +0 -275
- data/site/outdated/doc.ja/basics.html +0 -405
- data/site/outdated/doc.ja/config.html +0 -49
- data/site/outdated/doc.ja/details.html +0 -146
- data/site/outdated/doc.ja/index.html +0 -39
- data/site/outdated/doc.ja/mail.html +0 -793
- data/site/outdated/doc.ja/mailbox.html +0 -265
- data/site/outdated/doc.ja/port.html +0 -95
- data/site/outdated/doc.ja/tmail.html +0 -58
- data/site/outdated/doc.ja/usage.html +0 -202
- data/site/outdated/rdd/address.rrd.m +0 -229
- data/site/outdated/rdd/basics.rd.m +0 -275
- data/site/outdated/rdd/config.rrd.m +0 -26
- data/site/outdated/rdd/details.rd.m +0 -117
- data/site/outdated/rdd/index.rhtml.m +0 -54
- data/site/outdated/rdd/mail.rrd.m +0 -701
- data/site/outdated/rdd/mailbox.rrd.m +0 -228
- data/site/outdated/rdd/port.rrd.m +0 -69
- data/site/outdated/rdd/tmail.rrd.m +0 -33
- data/site/outdated/rdd/usage.rd.m +0 -247
- data/site/quickstart/index.html +0 -69
- data/site/quickstart/quickstart.html +0 -52
- data/site/quickstart/usage.html +0 -193
- data/site/reference/address.html +0 -247
- data/site/reference/config.html +0 -30
- data/site/reference/index.html +0 -101
- data/site/reference/mail.html +0 -726
- data/site/reference/mailbox.html +0 -245
- data/site/reference/port.html +0 -75
- data/site/reference/tmail.html +0 -35
- data/work/script/make +0 -26
- data/work/script/rdoc +0 -39
- data/work/script/setup +0 -1616
- data/work/script/test +0 -30
data/README
CHANGED
@@ -6,6 +6,16 @@
|
|
6
6
|
Trans assitant developer
|
7
7
|
Minero Aoki original developer
|
8
8
|
|
9
|
+
== RUBY 1.9 COMPATIBILITY
|
10
|
+
|
11
|
+
Note... as of 1.2.5, TMail is not compatible with Ruby 1.9.1. We are now using rchardet
|
12
|
+
to compare encodings and there is work to do for Ruby 1.9.1 due to it's encoding
|
13
|
+
capability.
|
14
|
+
|
15
|
+
For 1.9.1 + compatibility, I suggest you look at Mail (https://github.com/mikel/mail/tree)
|
16
|
+
while this is a work in progress, it is what I am working on to replace TMail for Ruby
|
17
|
+
1.9 and beyond.
|
18
|
+
|
9
19
|
== DESCRIPTION:
|
10
20
|
|
11
21
|
TMail is a mail handling library for Ruby. It abstracts a mail message into a usable object allowing you to read, set, add and delete headers and the mail body.
|
@@ -15,9 +15,27 @@
|
|
15
15
|
# include <stdlib.h>
|
16
16
|
#endif
|
17
17
|
|
18
|
+
|
18
19
|
#include "ruby.h"
|
20
|
+
#ifndef RSTRING_PTR
|
21
|
+
#define RSTRING_PTR(obj) RSTRING(obj)->ptr
|
22
|
+
#endif
|
23
|
+
|
24
|
+
#ifndef RSTRING_LEN
|
25
|
+
#define RSTRING_LEN(obj) RSTRING(obj)->len
|
26
|
+
#endif
|
27
|
+
|
28
|
+
#ifdef HAVE_RUBY_VM_H
|
29
|
+
#include "ruby/re.h"
|
30
|
+
#include "ruby/encoding.h"
|
31
|
+
#else
|
19
32
|
#include "re.h"
|
33
|
+
#endif
|
20
34
|
|
35
|
+
#ifdef HAVE_RUBY_VM_H
|
36
|
+
const unsigned char *re_mbctab;
|
37
|
+
#define ismbchar(c) re_mbctab[(unsigned char)(c)]
|
38
|
+
#endif
|
21
39
|
|
22
40
|
#define TMAIL_VERSION "1.2.3"
|
23
41
|
|
@@ -72,9 +90,9 @@ mails_s_new(klass, str, ident, cmt)
|
|
72
90
|
sc = ALLOC_N(struct scanner, 1);
|
73
91
|
|
74
92
|
StringValue(str);
|
75
|
-
sc->pbeg =
|
93
|
+
sc->pbeg = RSTRING_PTR(str);
|
76
94
|
sc->p = sc->pbeg;
|
77
|
-
sc->pend = sc->p +
|
95
|
+
sc->pend = sc->p + RSTRING_LEN(str);
|
78
96
|
|
79
97
|
sc->flags = 0;
|
80
98
|
Check_Type(ident, T_SYMBOL);
|
@@ -180,6 +198,18 @@ skip_iso2022jp_string(sc)
|
|
180
198
|
}
|
181
199
|
}
|
182
200
|
|
201
|
+
#ifdef HAVE_RUBY_VM_H
|
202
|
+
static void
|
203
|
+
skip_japanese_string(sc)
|
204
|
+
struct scanner *sc;
|
205
|
+
{
|
206
|
+
while(sc->p < sc->pend) {
|
207
|
+
if (! ismbchar(*sc->p)) return;
|
208
|
+
rb_encoding *enc = rb_enc_get(sc);
|
209
|
+
sc->p += mbclen(sc->p, sc->pend, enc);
|
210
|
+
}
|
211
|
+
}
|
212
|
+
#else
|
183
213
|
static void
|
184
214
|
skip_japanese_string(sc)
|
185
215
|
struct scanner *sc;
|
@@ -189,6 +219,7 @@ skip_japanese_string(sc)
|
|
189
219
|
sc->p += mbclen(*sc->p);
|
190
220
|
}
|
191
221
|
}
|
222
|
+
#endif
|
192
223
|
|
193
224
|
|
194
225
|
#define scan_atom(sc) scan_word(sc, ATOM_SYMBOLS)
|
@@ -376,9 +407,9 @@ digit_p(str)
|
|
376
407
|
char *p;
|
377
408
|
int i;
|
378
409
|
|
379
|
-
p =
|
380
|
-
for (i = 0; i <
|
381
|
-
if (! IS_DIGIT(
|
410
|
+
p = RSTRING_PTR(str);
|
411
|
+
for (i = 0; i < RSTRING_LEN(str); i++) {
|
412
|
+
if (! IS_DIGIT(RSTRING_PTR(str)[i]))
|
382
413
|
return 0;
|
383
414
|
}
|
384
415
|
return 1;
|
@@ -396,7 +427,7 @@ atomsym(sc, str)
|
|
396
427
|
return tok_digit;
|
397
428
|
}
|
398
429
|
else if (RECV_MODE_P(sc)) {
|
399
|
-
char *p =
|
430
|
+
char *p = RSTRING_PTR(str);
|
400
431
|
if (nccmp(p, "from")) return tok_from;
|
401
432
|
else if (nccmp(p, "by")) return tok_by;
|
402
433
|
else if (nccmp(p, "via")) return tok_via;
|
@@ -417,8 +448,8 @@ debug_print(sc, sym, val)
|
|
417
448
|
s = rb_funcall(sym, rb_intern("inspect"), 0),
|
418
449
|
printf("%7ld %-10s token=<%s>\n",
|
419
450
|
(unsigned long)(sc->pend - sc->p),
|
420
|
-
|
421
|
-
|
451
|
+
RSTRING_PTR(s),
|
452
|
+
RSTRING_PTR(val));
|
422
453
|
}
|
423
454
|
|
424
455
|
#define D(expr) do {\
|
data/lib/tmail.rb
CHANGED
data/lib/tmail/address.rb
CHANGED
@@ -38,7 +38,7 @@ module TMail
|
|
38
38
|
# = Class Address
|
39
39
|
#
|
40
40
|
# Provides a complete handling library for email addresses. Can parse a string of an
|
41
|
-
# address directly or take in preformatted addresses
|
41
|
+
# address directly or take in preformatted addresses themselves. Allows you to add
|
42
42
|
# and remove phrases from the front of the address and provides a compare function for
|
43
43
|
# email addresses.
|
44
44
|
#
|
@@ -46,7 +46,7 @@ module TMail
|
|
46
46
|
#
|
47
47
|
# Just pass the email address in as a string to Address.parse:
|
48
48
|
#
|
49
|
-
# email = TMail::Address.parse('Mikel Lindsaar <mikel@lindsaar.net>)
|
49
|
+
# email = TMail::Address.parse('Mikel Lindsaar <mikel@lindsaar.net>')
|
50
50
|
# #=> #<TMail::Address mikel@lindsaar.net>
|
51
51
|
# email.address
|
52
52
|
# #=> "mikel@lindsaar.net"
|
@@ -63,7 +63,7 @@ module TMail
|
|
63
63
|
# Address.parse and catch any SyntaxError:
|
64
64
|
#
|
65
65
|
# begin
|
66
|
-
# TMail::
|
66
|
+
# TMail::Address.parse("mikel 2@@@@@ me .com")
|
67
67
|
# rescue TMail::SyntaxError
|
68
68
|
# puts("Invalid Email Address Detected")
|
69
69
|
# else
|
@@ -81,41 +81,7 @@ module TMail
|
|
81
81
|
#
|
82
82
|
# Raises a TMail::SyntaxError on invalid email format
|
83
83
|
def Address.parse( str )
|
84
|
-
Parser.parse :ADDRESS,
|
85
|
-
end
|
86
|
-
|
87
|
-
def Address.special_quote_address(str) #:nodoc:
|
88
|
-
# Takes a string which is an address and adds quotation marks to special
|
89
|
-
# edge case methods that the RACC parser can not handle.
|
90
|
-
#
|
91
|
-
# Right now just handles two edge cases:
|
92
|
-
#
|
93
|
-
# Full stop as the last character of the display name:
|
94
|
-
# Mikel L. <mikel@me.com>
|
95
|
-
# Returns:
|
96
|
-
# "Mikel L." <mikel@me.com>
|
97
|
-
#
|
98
|
-
# Unquoted @ symbol in the display name:
|
99
|
-
# mikel@me.com <mikel@me.com>
|
100
|
-
# Returns:
|
101
|
-
# "mikel@me.com" <mikel@me.com>
|
102
|
-
#
|
103
|
-
# Any other address not matching these patterns just gets returned as is.
|
104
|
-
case
|
105
|
-
# This handles the missing "" in an older version of Apple Mail.app
|
106
|
-
# around the display name when the display name contains a '@'
|
107
|
-
# like 'mikel@me.com <mikel@me.com>'
|
108
|
-
# Just quotes it to: '"mikel@me.com" <mikel@me.com>'
|
109
|
-
when str =~ /\A([^"].+@.+[^"])\s(<.*?>)\Z/
|
110
|
-
return "\"#{$1}\" #{$2}"
|
111
|
-
# This handles cases where 'Mikel A. <mikel@me.com>' which is a trailing
|
112
|
-
# full stop before the address section. Just quotes it to
|
113
|
-
# '"Mikel A. <mikel@me.com>"
|
114
|
-
when str =~ /\A(.*?\.)\s(<.*?>)\Z/
|
115
|
-
return "\"#{$1}\" #{$2}"
|
116
|
-
else
|
117
|
-
str
|
118
|
-
end
|
84
|
+
Parser.parse :ADDRESS, str
|
119
85
|
end
|
120
86
|
|
121
87
|
def address_group? #:nodoc:
|
@@ -143,7 +109,7 @@ module TMail
|
|
143
109
|
|
144
110
|
# This is to catch an unquoted "@" symbol in the local part of the
|
145
111
|
# address. Handles addresses like <"@"@me.com> and makes sure they
|
146
|
-
# stay like <"@"@me.com> (previously were
|
112
|
+
# stay like <"@"@me.com> (previously were becoming <@@me.com>)
|
147
113
|
if local && (local.join == '@' || local.join =~ /\A[^"].*?@.*?[^"]\Z/)
|
148
114
|
@local = "\"#{local.join}\""
|
149
115
|
else
|
@@ -412,7 +378,7 @@ module TMail
|
|
412
378
|
if first
|
413
379
|
first = false
|
414
380
|
else
|
415
|
-
strategy.
|
381
|
+
strategy.puts_meta ','
|
416
382
|
end
|
417
383
|
strategy.space
|
418
384
|
mbox.accept strategy
|
data/lib/tmail/attachments.rb
CHANGED
@@ -4,43 +4,62 @@
|
|
4
4
|
|
5
5
|
=end
|
6
6
|
|
7
|
+
require 'kconv'
|
7
8
|
require 'stringio'
|
8
9
|
|
9
10
|
module TMail
|
10
11
|
class Attachment < StringIO
|
11
12
|
attr_accessor :original_filename, :content_type
|
13
|
+
alias quoted_filename original_filename
|
12
14
|
end
|
13
15
|
|
14
16
|
class Mail
|
15
17
|
def has_attachments?
|
16
|
-
multipart? && parts.any? { |part| attachment?(part) }
|
18
|
+
attachment?(self) || multipart? && parts.any? { |part| attachment?(part) }
|
17
19
|
end
|
18
20
|
|
21
|
+
# Returns true if this part's content main type is text, else returns false.
|
22
|
+
# By main type is meant "text/plain" is text. "text/html" is text
|
23
|
+
def text_content_type?
|
24
|
+
self.header['content-type'] && (self.header['content-type'].main_type == 'text')
|
25
|
+
end
|
26
|
+
|
27
|
+
def inline_attachment?(part)
|
28
|
+
part['content-id'] || (part['content-disposition'] && part['content-disposition'].disposition == 'inline' && !part.text_content_type?)
|
29
|
+
end
|
30
|
+
|
19
31
|
def attachment?(part)
|
20
|
-
part.disposition_is_attachment? || part.
|
32
|
+
part.disposition_is_attachment? || (!part.content_type.nil? && !part.text_content_type?) unless part.multipart?
|
21
33
|
end
|
22
|
-
|
34
|
+
|
23
35
|
def attachments
|
24
36
|
if multipart?
|
25
|
-
parts.collect { |part|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
content = part.body # unquoted automatically by TMail#body
|
30
|
-
file_name = (part['content-location'] &&
|
31
|
-
part['content-location'].body) ||
|
32
|
-
part.sub_header("content-type", "name") ||
|
33
|
-
part.sub_header("content-disposition", "filename")
|
34
|
-
|
35
|
-
next if file_name.blank? || content.blank?
|
36
|
-
|
37
|
-
attachment = Attachment.new(content)
|
38
|
-
attachment.original_filename = file_name.strip
|
39
|
-
attachment.content_type = part.content_type
|
40
|
-
attachment
|
41
|
-
end
|
42
|
-
}.flatten.compact
|
43
|
-
end
|
37
|
+
parts.collect { |part| attachment(part) }.flatten.compact
|
38
|
+
elsif attachment?(self)
|
39
|
+
[attachment(self)]
|
40
|
+
end
|
44
41
|
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def attachment(part)
|
46
|
+
if part.multipart?
|
47
|
+
part.attachments
|
48
|
+
elsif attachment?(part)
|
49
|
+
content = part.body # unquoted automatically by TMail#body
|
50
|
+
file_name = (part['content-location'] && part['content-location'].body) ||
|
51
|
+
part.sub_header('content-type', 'name') ||
|
52
|
+
part.sub_header('content-disposition', 'filename') ||
|
53
|
+
'noname'
|
54
|
+
|
55
|
+
return if content.blank?
|
56
|
+
|
57
|
+
attachment = TMail::Attachment.new(content)
|
58
|
+
attachment.original_filename = file_name.strip unless file_name.blank?
|
59
|
+
attachment.content_type = part.content_type
|
60
|
+
attachment
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
45
64
|
end
|
46
65
|
end
|
data/lib/tmail/encode.rb
CHANGED
@@ -113,6 +113,7 @@ module TMail
|
|
113
113
|
|
114
114
|
encoded = '=\?(?:iso-2022-jp|euc-jp|shift_jis)\?[QB]\?[a-z0-9+/=]+\?='
|
115
115
|
ENCODED_WORDS = /#{encoded}(?:\s+#{encoded})*/i
|
116
|
+
SPACER = "\t"
|
116
117
|
|
117
118
|
OUTPUT_ENCODING = {
|
118
119
|
'EUC' => 'e',
|
@@ -165,6 +166,10 @@ module TMail
|
|
165
166
|
@f << str
|
166
167
|
end
|
167
168
|
|
169
|
+
def puts_meta( str )
|
170
|
+
@f << str
|
171
|
+
end
|
172
|
+
|
168
173
|
def text( str )
|
169
174
|
@f << decode(str)
|
170
175
|
end
|
@@ -301,6 +306,10 @@ module TMail
|
|
301
306
|
add_text str
|
302
307
|
end
|
303
308
|
|
309
|
+
def puts_meta( str )
|
310
|
+
add_text str + @eol + SPACER
|
311
|
+
end
|
312
|
+
|
304
313
|
def text( str )
|
305
314
|
scanadd normalize_encoding(str)
|
306
315
|
end
|
data/lib/tmail/header.rb
CHANGED
@@ -59,7 +59,7 @@ module TMail
|
|
59
59
|
#
|
60
60
|
# This is because a mailbox doesn't have the : after the From that designates the
|
61
61
|
# beginning of the envelope sender (which can be different to the from address of
|
62
|
-
# the
|
62
|
+
# the email)
|
63
63
|
#
|
64
64
|
# Other fields can be passed as normal, "Reply-To", "Received" etc.
|
65
65
|
#
|
@@ -243,6 +243,8 @@ module TMail
|
|
243
243
|
|
244
244
|
def do_parse
|
245
245
|
quote_boundary
|
246
|
+
quote_unquoted_name
|
247
|
+
quote_unquoted_bencode
|
246
248
|
obj = Parser.parse(self.class::PARSE_TYPE, @body, @comments)
|
247
249
|
set obj if obj
|
248
250
|
end
|
@@ -314,7 +316,7 @@ module TMail
|
|
314
316
|
if first
|
315
317
|
first = false
|
316
318
|
else
|
317
|
-
strategy.
|
319
|
+
strategy.puts_meta ','
|
318
320
|
strategy.space
|
319
321
|
end
|
320
322
|
a.accept strategy
|
@@ -817,7 +819,7 @@ module TMail
|
|
817
819
|
if v
|
818
820
|
strategy.meta ';'
|
819
821
|
strategy.space
|
820
|
-
strategy.kv_pair k, v
|
822
|
+
strategy.kv_pair k, unquote(v)
|
821
823
|
end
|
822
824
|
end
|
823
825
|
end
|
data/lib/tmail/interface.rb
CHANGED
@@ -42,7 +42,7 @@ module TMail
|
|
42
42
|
# Allows you to query the mail object with a string to get the contents
|
43
43
|
# of the field you want.
|
44
44
|
#
|
45
|
-
# Returns a string of the exact
|
45
|
+
# Returns a string of the exact contents of the field
|
46
46
|
#
|
47
47
|
# mail.from = "mikel <mikel@lindsaar.net>"
|
48
48
|
# mail.header_string("From") #=> "mikel <mikel@lindsaar.net>"
|
@@ -591,16 +591,43 @@ module TMail
|
|
591
591
|
end
|
592
592
|
|
593
593
|
# Destructively sets the message ID of the mail object instance to the passed in string
|
594
|
+
#
|
595
|
+
# Invalid message IDs are ignored (silently, unless configured otherwise) and result in
|
596
|
+
# a nil message ID. Left and right angle brackets are required.
|
594
597
|
#
|
598
|
+
# Be warned however, that calling mail.ready_to_send will overwrite whatever value you
|
599
|
+
# have in this field with an automatically generated unique value.
|
600
|
+
#
|
601
|
+
# If you really want to set your own message ID and know what you are doing per the
|
602
|
+
# various RFCs, you can do so with the enforced_message_id= command
|
603
|
+
#
|
595
604
|
# Example:
|
596
605
|
#
|
597
606
|
# mail = TMail::Mail.new
|
607
|
+
# mail.message_id = "<348F04F142D69C21-291E56D292BC@xxxx.net>"
|
608
|
+
# mail.message_id #=> "<348F04F142D69C21-291E56D292BC@xxxx.net>"
|
598
609
|
# mail.message_id = "this_is_my_badly_formatted_message_id"
|
599
|
-
# mail.message_id #=>
|
610
|
+
# mail.message_id #=> nil
|
600
611
|
def message_id=( str )
|
601
612
|
set_string_attr 'Message-Id', str
|
602
613
|
end
|
603
614
|
|
615
|
+
# Destructively sets the message ID of the mail object instance to the passed in string
|
616
|
+
# and also guarantees that calling #ready_to_send will not destroy what you set as the
|
617
|
+
# message_id
|
618
|
+
#
|
619
|
+
# Example:
|
620
|
+
#
|
621
|
+
# mail = TMail::Mail.new
|
622
|
+
# mail.message_id = "<348F04F142D69C21-291E56D292BC@xxxx.net>"
|
623
|
+
# mail.message_id #=> "<348F04F142D69C21-291E56D292BC@xxxx.net>"
|
624
|
+
# mail.ready_to_send
|
625
|
+
# mail.message_id #=> "<348F04F142D69C21-291E56D292BC@xxxx.net>"
|
626
|
+
def enforced_message_id=( str )
|
627
|
+
@message_id_enforced = true
|
628
|
+
self.message_id = ( str )
|
629
|
+
end
|
630
|
+
|
604
631
|
# Returns the "In-Reply-To:" field contents as an array of this mail instance if it exists
|
605
632
|
#
|
606
633
|
# If the in_reply_to field does not exist, returns nil by default or you can pass in as
|
@@ -838,7 +865,17 @@ module TMail
|
|
838
865
|
if h = @header['content-type']
|
839
866
|
h['charset'] or default
|
840
867
|
else
|
841
|
-
default
|
868
|
+
mime_version_charset || default
|
869
|
+
end
|
870
|
+
end
|
871
|
+
|
872
|
+
# some weird emails come with the charset specified in the mime-version header:
|
873
|
+
#
|
874
|
+
# #<TMail::MimeVersionHeader "1.0\n charset=\"gb2312\"">
|
875
|
+
#
|
876
|
+
def mime_version_charset
|
877
|
+
if header['mime-version'].inspect =~ /charset=('|\\")?([^\\"']+)/
|
878
|
+
$2
|
842
879
|
end
|
843
880
|
end
|
844
881
|
|
data/lib/tmail/mail.rb
CHANGED
@@ -255,7 +255,7 @@ module TMail
|
|
255
255
|
alias fetch []
|
256
256
|
|
257
257
|
# Allows you to set or delete TMail header objects at will.
|
258
|
-
#
|
258
|
+
# Examples:
|
259
259
|
# @mail = TMail::Mail.new
|
260
260
|
# @mail['to'].to_s # => 'mikel@test.com.au'
|
261
261
|
# @mail['to'] = 'mikel@elsewhere.org'
|
@@ -265,7 +265,7 @@ module TMail
|
|
265
265
|
# @mail['to'].to_s # => nil
|
266
266
|
# @mail.encoded # => "\r\n"
|
267
267
|
#
|
268
|
-
# Note: setting mail[] = nil
|
268
|
+
# Note: setting mail[] = nil actually deletes the header field in question from the object,
|
269
269
|
# it does not just set the value of the hash to nil
|
270
270
|
def []=( key, val )
|
271
271
|
dkey = key.downcase
|
@@ -547,7 +547,7 @@ module TMail
|
|
547
547
|
end
|
548
548
|
|
549
549
|
def read_multipart( src )
|
550
|
-
bound = @header['content-type'].params['boundary']
|
550
|
+
bound = @header['content-type'].params['boundary'] || ::TMail.new_boundary
|
551
551
|
is_sep = /\A--#{Regexp.quote bound}(?:--)?[ \t]*(?:\n|\r\n|\r)/
|
552
552
|
lastbound = "--#{bound}--"
|
553
553
|
|