actionmailer 0.9.1 → 1.0.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.
- data/CHANGELOG +51 -2
- data/README +5 -6
- data/lib/action_mailer.rb +10 -3
- data/lib/action_mailer/adv_attr_accessor.rb +56 -0
- data/lib/action_mailer/base.rb +244 -120
- data/lib/action_mailer/helpers.rb +115 -0
- data/lib/action_mailer/part.rb +76 -0
- data/lib/action_mailer/part_container.rb +25 -0
- data/lib/action_mailer/quoting.rb +99 -0
- data/lib/action_mailer/utils.rb +8 -0
- data/lib/action_mailer/vendor/tmail/attachments.rb +6 -5
- data/lib/action_mailer/vendor/tmail/encode.rb +1 -0
- data/lib/action_mailer/vendor/tmail/facade.rb +2 -1
- data/lib/action_mailer/vendor/tmail/mail.rb +4 -0
- data/lib/action_mailer/vendor/tmail/net.rb +1 -1
- data/lib/action_mailer/vendor/tmail/quoting.rb +103 -80
- data/lib/action_mailer/vendor/tmail/scanner_r.rb +2 -2
- data/lib/action_mailer/vendor/tmail/utils.rb +9 -5
- data/rakefile +4 -4
- data/test/fixtures/helper_mailer/use_helper.rhtml +1 -0
- data/test/fixtures/helper_mailer/use_helper_method.rhtml +1 -0
- data/test/fixtures/helper_mailer/use_mail_helper.rhtml +5 -0
- data/test/fixtures/helper_mailer/use_test_helper.rhtml +1 -0
- data/test/fixtures/helpers/test_helper.rb +5 -0
- data/test/fixtures/raw_email +14 -0
- data/test/fixtures/raw_email10 +20 -0
- data/test/fixtures/raw_email11 +34 -0
- data/test/fixtures/raw_email2 +114 -0
- data/test/fixtures/raw_email3 +70 -0
- data/test/fixtures/raw_email4 +59 -0
- data/test/fixtures/raw_email5 +19 -0
- data/test/fixtures/raw_email6 +20 -0
- data/test/fixtures/raw_email7 +56 -0
- data/test/fixtures/raw_email8 +47 -0
- data/test/fixtures/raw_email9 +28 -0
- data/test/fixtures/test_mailer/implicitly_multipart_example.text.html.rhtml +10 -0
- data/test/fixtures/test_mailer/implicitly_multipart_example.text.plain.rhtml +2 -0
- data/test/fixtures/test_mailer/implicitly_multipart_example.text.yaml.rhtml +1 -0
- data/test/mail_helper_test.rb +97 -0
- data/test/mail_service_test.rb +391 -30
- metadata +32 -4
data/CHANGELOG
CHANGED
@@ -1,3 +1,52 @@
|
|
1
|
+
*1.0.0* (6 July, 2005)
|
2
|
+
|
3
|
+
* Avoid adding nil header values #1392
|
4
|
+
|
5
|
+
* Better multipart support with implicit multipart/alternative and sorting of subparts [John Long]
|
6
|
+
|
7
|
+
* Allow for nested parts in multipart mails #1570 [Flurin Egger]
|
8
|
+
|
9
|
+
* Normalize line endings in outgoing mail bodies to "\n" #1536 [John Long]
|
10
|
+
|
11
|
+
* Allow template to be explicitly specified #1448 [tuxie@dekadance.se]
|
12
|
+
|
13
|
+
* Allow specific "multipart/xxx" content-type to be set on multipart messages #1412 [Flurin Egger]
|
14
|
+
|
15
|
+
* Unquoted @ characters in headers are now accepted in spite of RFC 822 #1206
|
16
|
+
|
17
|
+
* Helper support (borrowed from ActionPack)
|
18
|
+
|
19
|
+
* Silently ignore Errno::EINVAL errors when converting text.
|
20
|
+
|
21
|
+
* Don't cause an error when parsing an encoded attachment name #1340 [lon@speedymac.com]
|
22
|
+
|
23
|
+
* Nested multipart message parts are correctly processed in TMail::Mail#body
|
24
|
+
|
25
|
+
* BCC headers are removed when sending via SMTP #1402
|
26
|
+
|
27
|
+
* Added 'content_type' accessor, to allow content type to be set on a per-message basis. content_type defaults to "text/plain".
|
28
|
+
|
29
|
+
* Silently ignore Iconv::IllegalSequence errors when converting text #1341 [lon@speedymac.com]
|
30
|
+
|
31
|
+
* Support attachments and multipart messages.
|
32
|
+
|
33
|
+
* Added new accessors for the various mail properties.
|
34
|
+
|
35
|
+
* Fix to only perform the charset conversion if a 'from' and a 'to' charset are given (make no assumptions about what the charset was) #1276 [Jamis Buck]
|
36
|
+
|
37
|
+
* Fix attachments and content-type problems #1276 [Jamis Buck]
|
38
|
+
|
39
|
+
* Fixed the TMail#body method to look at the content-transfer-encoding header and unquote the body according to the rules it specifies #1265 [Jamis Buck]
|
40
|
+
|
41
|
+
* Added unquoting even if the iconv lib can't be loaded--in that case, only the charset conversion is skipped #1265 [Jamis Buck]
|
42
|
+
|
43
|
+
* Added automatic decoding of base64 bodies #1214 [Jamis Buck]
|
44
|
+
|
45
|
+
* Added that delivery errors are caught in a way so the mail is still returned whether the delivery was successful or not
|
46
|
+
|
47
|
+
* Fixed that email address like "Jamis Buck, M.D." <wild.medicine@example.net> would cause the quoter to generate emails resulting in "bad address" errors from the mail server #1220 [Jamis Buck]
|
48
|
+
|
49
|
+
|
1
50
|
*0.9.1* (20th April, 2005)
|
2
51
|
|
3
52
|
* Depend on Action Pack 1.8.1
|
@@ -87,7 +136,7 @@
|
|
87
136
|
* Consolidated the server configuration options into Base#server_settings= and expanded that with controls for authentication and more [Marten]
|
88
137
|
NOTE: This is an API change that could potentially break your application if you used the old application form. Please do change!
|
89
138
|
|
90
|
-
* Added Base#deliveries as an accessor for an array of emails sent out through that ActionMailer class when using the :test delivery option. [
|
139
|
+
* Added Base#deliveries as an accessor for an array of emails sent out through that ActionMailer class when using the :test delivery option. [Jeremy Kemper]
|
91
140
|
|
92
141
|
* Added Base#perform_deliveries= which can be set to false to turn off the actual delivery of the email through smtp or sendmail.
|
93
142
|
This is especially useful for functional testing that shouldn't send off real emails, but still trigger delivery_* methods.
|
@@ -100,4 +149,4 @@
|
|
100
149
|
|
101
150
|
*0.3*
|
102
151
|
|
103
|
-
* First release
|
152
|
+
* First release
|
data/README
CHANGED
@@ -16,16 +16,15 @@ in methods on the service layer. Subject, recipients, sender, and timestamp
|
|
16
16
|
are all set up this way. An example of such a method:
|
17
17
|
|
18
18
|
def signed_up(recipient)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
@sent_on = Time.local(2004, 12, 12)
|
19
|
+
recipients recipient
|
20
|
+
subject "[Signed up] Welcome #{recipient}"
|
21
|
+
from "system@loudthinking.com"
|
23
22
|
|
24
|
-
|
23
|
+
body(:recipient => recipient)
|
25
24
|
end
|
26
25
|
|
27
26
|
The body of the email is created by using an Action View template (regular
|
28
|
-
ERb) that has the content of the
|
27
|
+
ERb) that has the content of the body hash parameter available as instance variables.
|
29
28
|
So the corresponding body template for the method above could look like this:
|
30
29
|
|
31
30
|
Hello there,
|
data/lib/action_mailer.rb
CHANGED
@@ -28,19 +28,26 @@ rescue LoadError
|
|
28
28
|
require File.dirname(__FILE__) + '/../../actionpack/lib/action_controller'
|
29
29
|
rescue LoadError
|
30
30
|
require 'rubygems'
|
31
|
-
require_gem 'actionpack', '>= 1.
|
31
|
+
require_gem 'actionpack', '>= 1.9.0'
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
$:.unshift(File.dirname(__FILE__) + "/action_mailer/vendor/")
|
36
36
|
|
37
37
|
require 'action_mailer/base'
|
38
|
+
require 'action_mailer/helpers'
|
38
39
|
require 'action_mailer/mail_helper'
|
40
|
+
require 'action_mailer/quoting'
|
39
41
|
require 'action_mailer/vendor/tmail'
|
40
42
|
require 'net/smtp'
|
41
43
|
|
42
|
-
|
44
|
+
ActionMailer::Base.class_eval do
|
45
|
+
include ActionMailer::Quoting
|
46
|
+
include ActionMailer::Helpers
|
47
|
+
|
48
|
+
helper MailHelper
|
49
|
+
end
|
43
50
|
|
44
51
|
old_verbose, $VERBOSE = $VERBOSE, nil
|
45
52
|
TMail::Encoder.const_set("MAX_LINE_LEN", 200)
|
46
|
-
$VERBOSE = old_verbose
|
53
|
+
$VERBOSE = old_verbose
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module ActionMailer
|
2
|
+
module AdvAttrAccessor #:nodoc:
|
3
|
+
def self.append_features(base)
|
4
|
+
super
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods #:nodoc:
|
9
|
+
def adv_attr_accessor(*names)
|
10
|
+
names.each do |name|
|
11
|
+
define_method("#{name}=") do |value|
|
12
|
+
instance_variable_set("@#{name}", value)
|
13
|
+
end
|
14
|
+
|
15
|
+
define_method(name) do |*parameters|
|
16
|
+
raise ArgumentError, "expected 0 or 1 parameters" unless parameters.length <= 1
|
17
|
+
if parameters.empty?
|
18
|
+
instance_variable_get("@#{name}")
|
19
|
+
else
|
20
|
+
instance_variable_set("@#{name}", parameters.first)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
module ActionMailer
|
30
|
+
module AdvAttrAccessor #:nodoc:
|
31
|
+
def self.append_features(base)
|
32
|
+
super
|
33
|
+
base.extend(ClassMethods)
|
34
|
+
end
|
35
|
+
|
36
|
+
module ClassMethods #:nodoc:
|
37
|
+
def adv_attr_accessor(*names)
|
38
|
+
names.each do |name|
|
39
|
+
define_method("#{name}=") do |value|
|
40
|
+
instance_variable_set("@#{name}", value)
|
41
|
+
end
|
42
|
+
|
43
|
+
define_method(name) do |*parameters|
|
44
|
+
raise ArgumentError, "expected 0 or 1 parameters" unless parameters.length <= 1
|
45
|
+
if parameters.empty?
|
46
|
+
instance_variable_get("@#{name}")
|
47
|
+
else
|
48
|
+
instance_variable_set("@#{name}", parameters.first)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/action_mailer/base.rb
CHANGED
@@ -1,23 +1,73 @@
|
|
1
|
+
require 'action_mailer/adv_attr_accessor'
|
2
|
+
require 'action_mailer/part'
|
3
|
+
require 'action_mailer/part_container'
|
4
|
+
require 'action_mailer/utils'
|
5
|
+
require 'tmail/net'
|
6
|
+
|
1
7
|
module ActionMailer #:nodoc:
|
2
8
|
# Usage:
|
3
9
|
#
|
4
10
|
# class ApplicationMailer < ActionMailer::Base
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
11
|
+
# # Set up properties
|
12
|
+
# # (Properties can also be specified via accessor methods
|
13
|
+
# # i.e. self.subject = "foo") and instance variables (@subject = "foo").
|
14
|
+
# def signup_notification(recipient)
|
15
|
+
# recipients recipient.email_address_with_name
|
16
|
+
# subject "New account information"
|
17
|
+
# body { "account" => recipient }
|
18
|
+
# from "system@example.com"
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# # explicitly specify multipart messages
|
22
|
+
# def signup_notification(recipient)
|
23
|
+
# recipients recipient.email_address_with_name
|
24
|
+
# subject "New account information"
|
25
|
+
# from "system@example.com"
|
26
|
+
#
|
27
|
+
# part :content_type => "text/html",
|
28
|
+
# :body => render_message("signup-as-html", :account => recipient)
|
29
|
+
#
|
30
|
+
# part "text/plain" do |p|
|
31
|
+
# p.body = render_message("signup-as-plain", :account => recipient)
|
32
|
+
# p.transfer_encoding = "base64"
|
33
|
+
# end
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# # attachments
|
37
|
+
# def signup_notification(recipient)
|
38
|
+
# recipients recipient.email_address_with_name
|
39
|
+
# subject "New account information"
|
40
|
+
# from "system@example.com"
|
41
|
+
#
|
42
|
+
# attachment :content_type => "image/jpeg",
|
43
|
+
# :body => File.read("an-image.jpg")
|
44
|
+
#
|
45
|
+
# attachment "application/pdf" do |a|
|
46
|
+
# a.body = generate_your_pdf_here()
|
47
|
+
# end
|
12
48
|
# end
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
# @
|
19
|
-
#
|
20
|
-
#
|
49
|
+
#
|
50
|
+
# # implicitly multipart messages
|
51
|
+
# def signup_notification(recipient)
|
52
|
+
# recipients recipient.email_address_with_name
|
53
|
+
# subject "New account information"
|
54
|
+
# from "system@example.com"
|
55
|
+
# body(:account => "recipient")
|
56
|
+
#
|
57
|
+
# # ActionMailer will automatically detect and use multipart templates,
|
58
|
+
# # where each template is named after the name of the action, followed
|
59
|
+
# # by the content type. Each such detected template will be added as
|
60
|
+
# # a separate part to the message.
|
61
|
+
# #
|
62
|
+
# # for example, if the following templates existed:
|
63
|
+
# # * signup_notification.text.plain.rhtml
|
64
|
+
# # * signup_notification.text.html.rhtml
|
65
|
+
# # * signup_notification.text.xml.rxml
|
66
|
+
# # * signup_notification.text.x-yaml.rhtml
|
67
|
+
# #
|
68
|
+
# # Each would be rendered and added as a separate part to the message,
|
69
|
+
# # with the corresponding content type. The same body hash is passed to
|
70
|
+
# # each template.
|
21
71
|
# end
|
22
72
|
# end
|
23
73
|
#
|
@@ -57,8 +107,18 @@ module ActionMailer #:nodoc:
|
|
57
107
|
# for unit and functional testing.
|
58
108
|
#
|
59
109
|
# * <tt>default_charset</tt> - The default charset used for the body and to encode the subject. Defaults to UTF-8. You can also
|
60
|
-
#
|
110
|
+
# pick a different charset from inside a method with <tt>@charset</tt>.
|
111
|
+
# * <tt>default_content_type</tt> - The default content type used for main part of the message. Defaults to "text/plain". You
|
112
|
+
# can also pick a different content type from inside a method with <tt>@content_type</tt>.
|
113
|
+
# * <tt>default_implicit_parts_order</tt> - When a message is built implicitly (i.e. multiple parts are assemble from templates
|
114
|
+
# which specify the content type in their filenames) this variable controls how the parts are ordered. Defaults to
|
115
|
+
# ["text/html", "text/enriched", "text/plain"]. Items that appear first in the array have higher priority in the mail client
|
116
|
+
# and appear last in the mime encoded message. You can also pick a different order from inside a method with
|
117
|
+
# <tt>@implicit_parts_order</tt>.
|
61
118
|
class Base
|
119
|
+
include ActionMailer::AdvAttrAccessor
|
120
|
+
include ActionMailer::PartContainer
|
121
|
+
|
62
122
|
private_class_method :new #:nodoc:
|
63
123
|
|
64
124
|
cattr_accessor :template_root
|
@@ -89,146 +149,210 @@ module ActionMailer #:nodoc:
|
|
89
149
|
@@default_charset = "utf-8"
|
90
150
|
cattr_accessor :default_charset
|
91
151
|
|
92
|
-
|
152
|
+
@@default_content_type = "text/plain"
|
153
|
+
cattr_accessor :default_content_type
|
154
|
+
|
155
|
+
@@default_implicit_parts_order = [ "text/html", "text/enriched", "text/plain" ]
|
156
|
+
cattr_accessor :default_implicit_parts_order
|
157
|
+
|
158
|
+
adv_attr_accessor :recipients, :subject, :body, :from, :sent_on, :headers,
|
159
|
+
:bcc, :cc, :charset, :content_type, :implicit_parts_order,
|
160
|
+
:template
|
93
161
|
|
94
|
-
|
95
|
-
|
162
|
+
attr_reader :mail
|
163
|
+
|
164
|
+
# Instantiate a new mailer object. If +method_name+ is not +nil+, the mailer
|
165
|
+
# will be initialized according to the named method. If not, the mailer will
|
166
|
+
# remain uninitialized (useful when you only need to invoke the "receive"
|
167
|
+
# method, for instance).
|
168
|
+
def initialize(method_name=nil, *parameters) #:nodoc:
|
169
|
+
create!(method_name, *parameters) if method_name
|
170
|
+
end
|
171
|
+
|
172
|
+
# Initialize the mailer via the given +method_name+. The body will be
|
173
|
+
# rendered and a new TMail::Mail object created.
|
174
|
+
def create!(method_name, *parameters) #:nodoc:
|
175
|
+
@bcc = @cc = @from = @recipients = @sent_on = @subject = nil
|
96
176
|
@charset = @@default_charset.dup
|
177
|
+
@content_type = @@default_content_type.dup
|
178
|
+
@implicit_parts_order = @@default_implicit_parts_order.dup
|
179
|
+
@template = method_name
|
180
|
+
@parts = []
|
97
181
|
@headers = {}
|
98
|
-
|
182
|
+
@body = {}
|
99
183
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
184
|
+
send(method_name, *parameters)
|
185
|
+
|
186
|
+
# If an explicit, textual body has not been set, we check assumptions.
|
187
|
+
unless String === @body
|
188
|
+
# First, we look to see if there are any likely templates that match,
|
189
|
+
# which include the content-type in their file name (i.e.,
|
190
|
+
# "the_template_file.text.html.rhtml", etc.).
|
191
|
+
if @parts.empty?
|
192
|
+
templates = Dir.glob("#{template_path}/#{@template}.*")
|
193
|
+
templates.each do |path|
|
194
|
+
type = (File.basename(path).split(".")[1..-2] || []).join("/")
|
195
|
+
next if type.empty?
|
196
|
+
@parts << Part.new(:content_type => type,
|
197
|
+
:disposition => "inline", :charset => charset,
|
198
|
+
:body => render_message(File.basename(path).split(".")[0..-2].join('.'), @body))
|
199
|
+
end
|
200
|
+
unless @parts.empty?
|
201
|
+
@content_type = "multipart/alternative"
|
202
|
+
@parts = sort_parts(@parts, @implicit_parts_order)
|
203
|
+
end
|
111
204
|
end
|
112
|
-
end
|
113
205
|
|
114
|
-
|
115
|
-
|
206
|
+
# Then, if there were such templates, we check to see if we ought to
|
207
|
+
# also render a "normal" template (without the content type). If a
|
208
|
+
# normal template exists (or if there were no implicit parts) we render
|
209
|
+
# it.
|
210
|
+
template_exists = @parts.empty?
|
211
|
+
template_exists ||= Dir.glob("#{template_path}/#{@template}.*").any? { |i| i.split(".").length == 2 }
|
212
|
+
@body = render_message(@template, @body) if template_exists
|
213
|
+
|
214
|
+
# Finally, if there are other message parts and a textual body exists,
|
215
|
+
# we shift it onto the front of the parts and set the body to nil (so
|
216
|
+
# that create_mail doesn't try to render it in addition to the parts).
|
217
|
+
if !@parts.empty? && String === @body
|
218
|
+
@parts.unshift Part.new(:charset => charset, :body => @body)
|
219
|
+
@body = nil
|
220
|
+
end
|
116
221
|
end
|
117
222
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
m.subject, = quote_any_if_necessary(charset, subject)
|
122
|
-
m.to, m.from = quote_any_address_if_necessary(charset, to, from)
|
223
|
+
# build the mail object itself
|
224
|
+
@mail = create_mail
|
225
|
+
end
|
123
226
|
|
124
|
-
|
227
|
+
# Delivers the cached TMail::Mail object. If no TMail::Mail object has been
|
228
|
+
# created (via the #create! method, for instance) this will fail.
|
229
|
+
def deliver! #:nodoc:
|
230
|
+
raise "no mail object available for delivery!" unless @mail
|
231
|
+
logger.info "Sent mail:\n #{mail.encoded}" unless logger.nil?
|
125
232
|
|
126
|
-
|
233
|
+
begin
|
234
|
+
send("perform_delivery_#{delivery_method}", @mail) if perform_deliveries
|
235
|
+
rescue Object => e
|
236
|
+
raise e if raise_delivery_errors
|
237
|
+
end
|
127
238
|
|
128
|
-
|
129
|
-
|
130
|
-
end
|
239
|
+
return @mail
|
240
|
+
end
|
131
241
|
|
132
|
-
|
242
|
+
private
|
243
|
+
def render_message(method_name, body)
|
244
|
+
initialize_template_class(body).render_file(method_name)
|
133
245
|
end
|
134
|
-
|
135
|
-
def
|
136
|
-
|
137
|
-
send("perform_delivery_#{delivery_method}", mail) if perform_deliveries
|
138
|
-
return mail
|
246
|
+
|
247
|
+
def template_path
|
248
|
+
template_root + "/" + Inflector.underscore(self.class.name)
|
139
249
|
end
|
140
250
|
|
141
|
-
def
|
142
|
-
|
143
|
-
"=?#{charset}?Q?#{text}?="
|
251
|
+
def initialize_template_class(assigns)
|
252
|
+
ActionView::Base.new(template_path, assigns, self)
|
144
253
|
end
|
145
254
|
|
146
|
-
|
255
|
+
def sort_parts(parts, order = [])
|
256
|
+
order = order.collect { |s| s.downcase }
|
147
257
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
quoted_printable(text, charset) :
|
152
|
-
text
|
153
|
-
end
|
258
|
+
parts = parts.sort do |a, b|
|
259
|
+
a_ct = a.content_type.downcase
|
260
|
+
b_ct = b.content_type.downcase
|
154
261
|
|
155
|
-
|
156
|
-
|
157
|
-
args.map { |v| quote_if_necessary(v, charset) }
|
158
|
-
end
|
262
|
+
a_in = order.include? a_ct
|
263
|
+
b_in = order.include? b_ct
|
159
264
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
265
|
+
s = case
|
266
|
+
when a_in && b_in
|
267
|
+
order.index(a_ct) <=> order.index(b_ct)
|
268
|
+
when a_in
|
269
|
+
-1
|
270
|
+
when b_in
|
271
|
+
1
|
272
|
+
else
|
273
|
+
a_ct <=> b_ct
|
274
|
+
end
|
275
|
+
|
276
|
+
# reverse the ordering because parts that come last are displayed
|
277
|
+
# first in mail clients
|
278
|
+
(s * -1)
|
174
279
|
end
|
175
|
-
end
|
176
280
|
|
177
|
-
|
178
|
-
def quote_any_address_if_necessary(charset, *args)
|
179
|
-
args.map { |v| quote_address_if_necessary(v, charset) }
|
281
|
+
parts
|
180
282
|
end
|
181
283
|
|
182
|
-
def
|
183
|
-
|
184
|
-
|
185
|
-
|
284
|
+
def create_mail
|
285
|
+
m = TMail::Mail.new
|
286
|
+
|
287
|
+
m.subject, = quote_any_if_necessary(charset, subject)
|
288
|
+
m.to, m.from = quote_any_address_if_necessary(charset, recipients, from)
|
289
|
+
m.bcc = quote_address_if_necessary(bcc, charset) unless bcc.nil?
|
290
|
+
m.cc = quote_address_if_necessary(cc, charset) unless cc.nil?
|
186
291
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
292
|
+
m.date = sent_on.to_time rescue sent_on if sent_on
|
293
|
+
headers.each { |k, v| m[k] = v }
|
294
|
+
|
295
|
+
if @parts.empty?
|
296
|
+
m.set_content_type content_type, nil, { "charset" => charset }
|
297
|
+
m.body = Utils.normalize_new_lines(body)
|
298
|
+
else
|
299
|
+
if String === body
|
300
|
+
part = TMail::Mail.new
|
301
|
+
part.body = Utils.normalize_new_lines(body)
|
302
|
+
part.set_content_type content_type, nil, { "charset" => charset }
|
303
|
+
part.set_content_disposition "inline"
|
304
|
+
m.parts << part
|
192
305
|
end
|
193
|
-
end
|
194
306
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
sm.flush
|
307
|
+
@parts.each do |p|
|
308
|
+
part = (TMail::Mail === p ? p : p.to_mail(self))
|
309
|
+
m.parts << part
|
199
310
|
end
|
311
|
+
|
312
|
+
m.set_content_type(content_type, nil, { "charset" => charset }) if content_type =~ /multipart/
|
200
313
|
end
|
201
314
|
|
202
|
-
|
203
|
-
|
204
|
-
end
|
315
|
+
@mail = m
|
316
|
+
end
|
205
317
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
mailer.send(method_name, *parameters)
|
318
|
+
def perform_delivery_smtp(mail)
|
319
|
+
destinations = mail.destinations
|
320
|
+
mail.ready_to_send
|
210
321
|
|
211
|
-
|
212
|
-
|
213
|
-
|
322
|
+
Net::SMTP.start(server_settings[:address], server_settings[:port], server_settings[:domain],
|
323
|
+
server_settings[:user_name], server_settings[:password], server_settings[:authentication]) do |smtp|
|
324
|
+
smtp.sendmail(mail.encoded, mail.from, destinations)
|
325
|
+
end
|
326
|
+
end
|
214
327
|
|
215
|
-
|
216
|
-
|
217
|
-
|
328
|
+
def perform_delivery_sendmail(mail)
|
329
|
+
IO.popen("/usr/sbin/sendmail -i -t","w+") do |sm|
|
330
|
+
sm.print(mail.encoded)
|
331
|
+
sm.flush
|
332
|
+
end
|
333
|
+
end
|
218
334
|
|
219
|
-
|
220
|
-
|
335
|
+
def perform_delivery_test(mail)
|
336
|
+
deliveries << mail
|
337
|
+
end
|
221
338
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
def template_path
|
230
|
-
template_root + "/" + Inflector.underscore(self.to_s)
|
339
|
+
class << self
|
340
|
+
def method_missing(method_symbol, *parameters)#:nodoc:
|
341
|
+
case method_symbol.id2name
|
342
|
+
when /^create_([_a-z]\w*)/ then new($1, *parameters).mail
|
343
|
+
when /^deliver_([_a-z]\w*)/ then new($1, *parameters).deliver!
|
344
|
+
when "new" then nil
|
345
|
+
else super
|
231
346
|
end
|
347
|
+
end
|
348
|
+
|
349
|
+
def receive(raw_email)
|
350
|
+
logger.info "Received mail:\n #{raw_email}" unless logger.nil?
|
351
|
+
mail = TMail::Mail.parse(raw_email)
|
352
|
+
mail.base64_decode
|
353
|
+
new.receive(mail)
|
354
|
+
end
|
355
|
+
|
232
356
|
end
|
233
357
|
end
|
234
358
|
end
|