actionmailer 0.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionmailer might be problematic. Click here for more details.

Files changed (34) hide show
  1. data/CHANGELOG +3 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +102 -0
  4. data/install.rb +61 -0
  5. data/lib/action_mailer.rb +44 -0
  6. data/lib/action_mailer/base.rb +111 -0
  7. data/lib/action_mailer/mail_helper.rb +17 -0
  8. data/lib/action_mailer/vendor/text/format.rb +1447 -0
  9. data/lib/action_mailer/vendor/tmail.rb +4 -0
  10. data/lib/action_mailer/vendor/tmail/address.rb +223 -0
  11. data/lib/action_mailer/vendor/tmail/base64.rb +52 -0
  12. data/lib/action_mailer/vendor/tmail/config.rb +50 -0
  13. data/lib/action_mailer/vendor/tmail/encode.rb +447 -0
  14. data/lib/action_mailer/vendor/tmail/facade.rb +531 -0
  15. data/lib/action_mailer/vendor/tmail/header.rb +893 -0
  16. data/lib/action_mailer/vendor/tmail/info.rb +16 -0
  17. data/lib/action_mailer/vendor/tmail/loader.rb +1 -0
  18. data/lib/action_mailer/vendor/tmail/mail.rb +420 -0
  19. data/lib/action_mailer/vendor/tmail/mailbox.rb +414 -0
  20. data/lib/action_mailer/vendor/tmail/mbox.rb +1 -0
  21. data/lib/action_mailer/vendor/tmail/net.rb +261 -0
  22. data/lib/action_mailer/vendor/tmail/obsolete.rb +116 -0
  23. data/lib/action_mailer/vendor/tmail/parser.rb +1503 -0
  24. data/lib/action_mailer/vendor/tmail/port.rb +358 -0
  25. data/lib/action_mailer/vendor/tmail/scanner.rb +22 -0
  26. data/lib/action_mailer/vendor/tmail/scanner_r.rb +244 -0
  27. data/lib/action_mailer/vendor/tmail/stringio.rb +260 -0
  28. data/lib/action_mailer/vendor/tmail/tmail.rb +1 -0
  29. data/lib/action_mailer/vendor/tmail/utils.rb +215 -0
  30. data/rakefile +99 -0
  31. data/test/fixtures/templates/signed_up.rhtml +3 -0
  32. data/test/fixtures/test_mailer/signed_up.rhtml +3 -0
  33. data/test/mail_service_test.rb +53 -0
  34. metadata +86 -0
@@ -0,0 +1,260 @@
1
+ #
2
+ # stringio.rb
3
+ #
4
+ # Copyright (c) 1999-2003 Minero Aoki <aamine@loveruby.net>
5
+ #
6
+ # This program is free software.
7
+ # You can distribute/modify this program under the terms of
8
+ # the GNU Lesser General Public License version 2 or later.
9
+ #
10
+ # Id: stringio.rb,v 1.10 2003/04/27 22:02:14 aamine Exp
11
+ #
12
+
13
+ class StringInput#:nodoc:
14
+
15
+ include Enumerable
16
+
17
+ class << self
18
+
19
+ def new( str )
20
+ if block_given?
21
+ begin
22
+ f = super
23
+ yield f
24
+ ensure
25
+ f.close if f
26
+ end
27
+ else
28
+ super
29
+ end
30
+ end
31
+
32
+ alias open new
33
+
34
+ end
35
+
36
+ def initialize( str )
37
+ @src = str
38
+ @pos = 0
39
+ @closed = false
40
+ @lineno = 0
41
+ end
42
+
43
+ attr_reader :lineno
44
+
45
+ def string
46
+ @src
47
+ end
48
+
49
+ def inspect
50
+ "#<#{self.class}:#{@closed ? 'closed' : 'open'},src=#{@src[0,30].inspect}>"
51
+ end
52
+
53
+ def close
54
+ stream_check!
55
+ @pos = nil
56
+ @closed = true
57
+ end
58
+
59
+ def closed?
60
+ @closed
61
+ end
62
+
63
+ def pos
64
+ stream_check!
65
+ [@pos, @src.size].min
66
+ end
67
+
68
+ alias tell pos
69
+
70
+ def seek( offset, whence = IO::SEEK_SET )
71
+ stream_check!
72
+ case whence
73
+ when IO::SEEK_SET
74
+ @pos = offset
75
+ when IO::SEEK_CUR
76
+ @pos += offset
77
+ when IO::SEEK_END
78
+ @pos = @src.size - offset
79
+ else
80
+ raise ArgumentError, "unknown seek flag: #{whence}"
81
+ end
82
+ @pos = 0 if @pos < 0
83
+ @pos = [@pos, @src.size + 1].min
84
+ offset
85
+ end
86
+
87
+ def rewind
88
+ stream_check!
89
+ @pos = 0
90
+ end
91
+
92
+ def eof?
93
+ stream_check!
94
+ @pos > @src.size
95
+ end
96
+
97
+ def each( &block )
98
+ stream_check!
99
+ begin
100
+ @src.each(&block)
101
+ ensure
102
+ @pos = 0
103
+ end
104
+ end
105
+
106
+ def gets
107
+ stream_check!
108
+ if idx = @src.index(?\n, @pos)
109
+ idx += 1 # "\n".size
110
+ line = @src[ @pos ... idx ]
111
+ @pos = idx
112
+ @pos += 1 if @pos == @src.size
113
+ else
114
+ line = @src[ @pos .. -1 ]
115
+ @pos = @src.size + 1
116
+ end
117
+ @lineno += 1
118
+
119
+ line
120
+ end
121
+
122
+ def getc
123
+ stream_check!
124
+ ch = @src[@pos]
125
+ @pos += 1
126
+ @pos += 1 if @pos == @src.size
127
+ ch
128
+ end
129
+
130
+ def read( len = nil )
131
+ stream_check!
132
+ return read_all unless len
133
+ str = @src[@pos, len]
134
+ @pos += len
135
+ @pos += 1 if @pos == @src.size
136
+ str
137
+ end
138
+
139
+ alias sysread read
140
+
141
+ def read_all
142
+ stream_check!
143
+ return nil if eof?
144
+ rest = @src[@pos ... @src.size]
145
+ @pos = @src.size + 1
146
+ rest
147
+ end
148
+
149
+ def stream_check!
150
+ @closed and raise IOError, 'closed stream'
151
+ end
152
+
153
+ end
154
+
155
+
156
+ class StringOutput#:nodoc:
157
+
158
+ class << self
159
+
160
+ def new( str = '' )
161
+ if block_given?
162
+ begin
163
+ f = super
164
+ yield f
165
+ ensure
166
+ f.close if f
167
+ end
168
+ else
169
+ super
170
+ end
171
+ end
172
+
173
+ alias open new
174
+
175
+ end
176
+
177
+ def initialize( str = '' )
178
+ @dest = str
179
+ @closed = false
180
+ end
181
+
182
+ def close
183
+ @closed = true
184
+ end
185
+
186
+ def closed?
187
+ @closed
188
+ end
189
+
190
+ def string
191
+ @dest
192
+ end
193
+
194
+ alias value string
195
+ alias to_str string
196
+
197
+ def size
198
+ @dest.size
199
+ end
200
+
201
+ alias pos size
202
+
203
+ def inspect
204
+ "#<#{self.class}:#{@dest ? 'open' : 'closed'},#{id}>"
205
+ end
206
+
207
+ def print( *args )
208
+ stream_check!
209
+ raise ArgumentError, 'wrong # of argument (0 for >1)' if args.empty?
210
+ args.each do |s|
211
+ raise ArgumentError, 'nil not allowed' if s.nil?
212
+ @dest << s.to_s
213
+ end
214
+ nil
215
+ end
216
+
217
+ def puts( *args )
218
+ stream_check!
219
+ args.each do |str|
220
+ @dest << (s = str.to_s)
221
+ @dest << "\n" unless s[-1] == ?\n
222
+ end
223
+ @dest << "\n" if args.empty?
224
+ nil
225
+ end
226
+
227
+ def putc( ch )
228
+ stream_check!
229
+ @dest << ch.chr
230
+ nil
231
+ end
232
+
233
+ def printf( *args )
234
+ stream_check!
235
+ @dest << sprintf(*args)
236
+ nil
237
+ end
238
+
239
+ def write( str )
240
+ stream_check!
241
+ s = str.to_s
242
+ @dest << s
243
+ s.size
244
+ end
245
+
246
+ alias syswrite write
247
+
248
+ def <<( str )
249
+ stream_check!
250
+ @dest << str.to_s
251
+ self
252
+ end
253
+
254
+ private
255
+
256
+ def stream_check!
257
+ @closed and raise IOError, 'closed stream'
258
+ end
259
+
260
+ end
@@ -0,0 +1 @@
1
+ require 'tmail'
@@ -0,0 +1,215 @@
1
+ #
2
+ # utils.rb
3
+ #
4
+ # Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
5
+ #
6
+ # This program is free software.
7
+ # You can distribute/modify this program under the terms of
8
+ # the GNU Lesser General Public License version 2 or later.
9
+ #
10
+
11
+ module TMail
12
+
13
+ class SyntaxError < StandardError; end
14
+
15
+
16
+ def TMail.new_boundary
17
+ 'mimepart_' + random_tag
18
+ end
19
+
20
+ def TMail.new_message_id( fqdn = nil )
21
+ fqdn ||= ::Socket.gethostname
22
+ "<#{random_tag()}@#{fqdn}.tmail>"
23
+ end
24
+
25
+ def TMail.random_tag
26
+ @uniq += 1
27
+ t = Time.now
28
+ sprintf('%x%x_%x%x%d%x',
29
+ t.to_i, t.tv_usec,
30
+ $$, Thread.current.id, @uniq, rand(255))
31
+ end
32
+ private_class_method :random_tag
33
+
34
+ @uniq = 0
35
+
36
+
37
+ module TextUtils
38
+
39
+ aspecial = '()<>[]:;.@\\,"'
40
+ tspecial = '()<>[];:@\\,"/?='
41
+ lwsp = " \t\r\n"
42
+ control = '\x00-\x1f\x7f-\xff'
43
+
44
+ ATOM_UNSAFE = /[#{Regexp.quote aspecial}#{control}#{lwsp}]/n
45
+ PHRASE_UNSAFE = /[#{Regexp.quote aspecial}#{control}]/n
46
+ TOKEN_UNSAFE = /[#{Regexp.quote tspecial}#{control}#{lwsp}]/n
47
+ CONTROL_CHAR = /[#{control}]/n
48
+
49
+ def atom_safe?( str )
50
+ not ATOM_UNSAFE === str
51
+ end
52
+
53
+ def quote_atom( str )
54
+ (ATOM_UNSAFE === str) ? dquote(str) : str
55
+ end
56
+
57
+ def quote_phrase( str )
58
+ (PHRASE_UNSAFE === str) ? dquote(str) : str
59
+ end
60
+
61
+ def token_safe?( str )
62
+ not TOKEN_UNSAFE === str
63
+ end
64
+
65
+ def quote_token( str )
66
+ (TOKEN_UNSAFE === str) ? dquote(str) : str
67
+ end
68
+
69
+ def dquote( str )
70
+ '"' + str.gsub(/["\\]/n) {|s| '\\' + s } + '"'
71
+ end
72
+ private :dquote
73
+
74
+
75
+ def join_domain( arr )
76
+ arr.map {|i|
77
+ if /\A\[.*\]\z/ === i
78
+ i
79
+ else
80
+ quote_atom(i)
81
+ end
82
+ }.join('.')
83
+ end
84
+
85
+
86
+ ZONESTR_TABLE = {
87
+ 'jst' => 9 * 60,
88
+ 'eet' => 2 * 60,
89
+ 'bst' => 1 * 60,
90
+ 'met' => 1 * 60,
91
+ 'gmt' => 0,
92
+ 'utc' => 0,
93
+ 'ut' => 0,
94
+ 'nst' => -(3 * 60 + 30),
95
+ 'ast' => -4 * 60,
96
+ 'edt' => -4 * 60,
97
+ 'est' => -5 * 60,
98
+ 'cdt' => -5 * 60,
99
+ 'cst' => -6 * 60,
100
+ 'mdt' => -6 * 60,
101
+ 'mst' => -7 * 60,
102
+ 'pdt' => -7 * 60,
103
+ 'pst' => -8 * 60,
104
+ 'a' => -1 * 60,
105
+ 'b' => -2 * 60,
106
+ 'c' => -3 * 60,
107
+ 'd' => -4 * 60,
108
+ 'e' => -5 * 60,
109
+ 'f' => -6 * 60,
110
+ 'g' => -7 * 60,
111
+ 'h' => -8 * 60,
112
+ 'i' => -9 * 60,
113
+ # j not use
114
+ 'k' => -10 * 60,
115
+ 'l' => -11 * 60,
116
+ 'm' => -12 * 60,
117
+ 'n' => 1 * 60,
118
+ 'o' => 2 * 60,
119
+ 'p' => 3 * 60,
120
+ 'q' => 4 * 60,
121
+ 'r' => 5 * 60,
122
+ 's' => 6 * 60,
123
+ 't' => 7 * 60,
124
+ 'u' => 8 * 60,
125
+ 'v' => 9 * 60,
126
+ 'w' => 10 * 60,
127
+ 'x' => 11 * 60,
128
+ 'y' => 12 * 60,
129
+ 'z' => 0 * 60
130
+ }
131
+
132
+ def timezone_string_to_unixtime( str )
133
+ if m = /([\+\-])(\d\d?)(\d\d)/.match(str)
134
+ sec = (m[2].to_i * 60 + m[3].to_i) * 60
135
+ m[1] == '-' ? -sec : sec
136
+ else
137
+ min = ZONESTR_TABLE[str.downcase] or
138
+ raise SyntaxError, "wrong timezone format '#{str}'"
139
+ min * 60
140
+ end
141
+ end
142
+
143
+
144
+ WDAY = %w( Sun Mon Tue Wed Thu Fri Sat TMailBUG )
145
+ MONTH = %w( TMailBUG Jan Feb Mar Apr May Jun
146
+ Jul Aug Sep Oct Nov Dec TMailBUG )
147
+
148
+ def time2str( tm )
149
+ # [ruby-list:7928]
150
+ gmt = Time.at(tm.to_i)
151
+ gmt.gmtime
152
+ offset = tm.to_i - Time.local(*gmt.to_a[0,6].reverse).to_i
153
+
154
+ # DO NOT USE strftime: setlocale() breaks it
155
+ sprintf '%s, %s %s %d %02d:%02d:%02d %+.2d%.2d',
156
+ WDAY[tm.wday], tm.mday, MONTH[tm.month],
157
+ tm.year, tm.hour, tm.min, tm.sec,
158
+ *(offset / 60).divmod(60)
159
+ end
160
+
161
+
162
+ MESSAGE_ID = /<[^\@>]+\@[^>\@]+>/
163
+
164
+ def message_id?( str )
165
+ MESSAGE_ID === str
166
+ end
167
+
168
+
169
+ MIME_ENCODED = /=\?[^\s?=]+\?[QB]\?[^\s?=]+\?=/i
170
+
171
+ def mime_encoded?( str )
172
+ MIME_ENCODED === str
173
+ end
174
+
175
+
176
+ def decode_params( hash )
177
+ new = Hash.new
178
+ encoded = nil
179
+ hash.each do |key, value|
180
+ if m = /\*(?:(\d+)\*)?\z/.match(key)
181
+ ((encoded ||= {})[m.pre_match] ||= [])[(m[1] || 0).to_i] = value
182
+ else
183
+ new[key] = to_kcode(value)
184
+ end
185
+ end
186
+ if encoded
187
+ encoded.each do |key, strings|
188
+ new[key] = decode_RFC2231(strings.join(''))
189
+ end
190
+ end
191
+
192
+ new
193
+ end
194
+
195
+ NKF_FLAGS = {
196
+ 'EUC' => '-e -m',
197
+ 'SJIS' => '-s -m'
198
+ }
199
+
200
+ def to_kcode( str )
201
+ flag = NKF_FLAGS[$KCODE] or return str
202
+ NKF.nkf(flag, str)
203
+ end
204
+
205
+ RFC2231_ENCODED = /\A(?:iso-2022-jp|euc-jp|shift_jis|us-ascii)?'[a-z]*'/in
206
+
207
+ def decode_RFC2231( str )
208
+ m = RFC2231_ENCODED.match(str) or return str
209
+ NKF.nkf(NKF_FLAGS[$KCODE],
210
+ m.post_match.gsub(/%[\da-f]{2}/in) {|s| s[1,2].hex.chr })
211
+ end
212
+
213
+ end
214
+
215
+ end