mail 1.2.1 → 1.2.5
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of mail might be problematic. Click here for more details.
- data/CHANGELOG.rdoc +42 -1
- data/Manifest.txt +6 -0
- data/README.rdoc +7 -2
- data/lib/mail.rb +6 -0
- data/lib/mail/body.rb +5 -0
- data/lib/mail/configuration.rb +67 -27
- data/lib/mail/fields/content_type_field.rb +11 -0
- data/lib/mail/fields/unstructured_field.rb +2 -2
- data/lib/mail/header.rb +1 -1
- data/lib/mail/mail.rb +66 -18
- data/lib/mail/message.rb +166 -13
- data/lib/mail/network/deliverable.rb +8 -39
- data/lib/mail/network/delivery_methods/file_delivery.rb +18 -0
- data/lib/mail/network/delivery_methods/sendmail.rb +18 -0
- data/lib/mail/network/delivery_methods/smtp.rb +87 -0
- data/lib/mail/network/delivery_methods/test_mailer.rb +10 -0
- data/lib/mail/network/retrievable.rb +3 -49
- data/lib/mail/network/retriever_methods/imap.rb +17 -0
- data/lib/mail/network/retriever_methods/pop3.rb +92 -0
- data/lib/mail/parsers/rfc2822.rb +77 -1
- data/lib/mail/parsers/rfc2822.treetop +9 -1
- data/lib/mail/part.rb +0 -53
- data/lib/mail/patterns.rb +1 -0
- data/lib/mail/utilities.rb +7 -3
- data/lib/mail/version.rb +1 -1
- metadata +7 -1
data/CHANGELOG.rdoc
CHANGED
@@ -1,6 +1,47 @@
|
|
1
|
+
== Fri Nov 13 00:31:04 UTC 2009 Mikel Lindsaar <raasdnil@gmail.com>
|
2
|
+
|
3
|
+
* Hacked and mutilated the network section, made it easier to extend out with other
|
4
|
+
delivery and retriever methods. API changed SLIGHTLY with this. Please check the
|
5
|
+
readme
|
6
|
+
* Version bump to 1.2.5
|
7
|
+
|
8
|
+
== Thu Nov 12 02:58:01 UTC 2009 Mikel Lindsaar <raasdnil@gmail.com>
|
9
|
+
|
10
|
+
* Resolved Issue #8 - Message ID not handling multiple periods in left hand side
|
11
|
+
* Resolved Issue #6 - Ordering of add_file and body items causes invalid emails
|
12
|
+
|
13
|
+
== Tue Nov 10 08:15:14 UTC 2009 Mikel Lindsaar <raasdnil@gmail.com>
|
14
|
+
|
15
|
+
* Resolved Issue #5 - Message ID generation issue
|
16
|
+
* Resolved Issue #7 - README add_file examples don't seem to work - Updated readme and
|
17
|
+
rdoc in Message#add_file
|
18
|
+
|
19
|
+
== Mon Nov 9 23:38:33 UTC 2009 Mikel Lindsaar <raasdnil@gmail.com>
|
20
|
+
|
21
|
+
* Added ability to create new email via a hash or hash-like object. <mikel>
|
22
|
+
* Moved all of the Part init into the Message class. Part now just uses Message's init,
|
23
|
+
also moved all the attachment related functions into Message. As Part is a subclass
|
24
|
+
of message, you shouldn't see any interface changes here.
|
25
|
+
|
26
|
+
== Fri Nov 6 22:52:10 UTC 2009 Mikel Lindsaar <raasdnil@gmail.com>
|
27
|
+
|
28
|
+
* a6ef2b4: Fixed Issue #4 - Can't call encoding on non existant
|
29
|
+
content-transer-encoding header
|
30
|
+
|
31
|
+
== Fri Nov 6 00:51:55 UTC 2009 Mikel Lindsaar <raasdnil@gmail.com>
|
32
|
+
|
33
|
+
* Handled unstructured field folding "blank" lines
|
34
|
+
* Fixed error in header.rb that created fields into an array, instead of a FieldList, resulting
|
35
|
+
in mail.encode returning a random sort order on the header.
|
36
|
+
* Made unstructured fields attempt to decode their values on :decode
|
37
|
+
|
38
|
+
== Thu Nov 5 04:45:31 UTC 2009 Mikel Lindsaar <raasdnil@gmail.com>
|
39
|
+
|
40
|
+
* 2acb70a: Closes Issue #1 - Handling badly formatted content-type fields <mikel>
|
41
|
+
|
1
42
|
== Wed Nov 4 23:24:32 UTC 2009 Mikel Lindsaar <raasdnil@gmail.com>
|
2
43
|
|
3
|
-
*
|
44
|
+
* 2b5d608: Closes Issue #2 - Empty header field values not parsing <mikel>
|
4
45
|
* Version bumb to 1.2.1
|
5
46
|
|
6
47
|
== Wed Nov 4 12:54:43 UTC 2009 Mikel Lindsaar <raasdnil@gmail.com>
|
data/Manifest.txt
CHANGED
@@ -70,7 +70,13 @@ lib/mail/header.rb
|
|
70
70
|
lib/mail/mail.rb
|
71
71
|
lib/mail/message.rb
|
72
72
|
lib/mail/network/deliverable.rb
|
73
|
+
lib/mail/network/delivery_methods/file_delivery.rb
|
74
|
+
lib/mail/network/delivery_methods/sendmail.rb
|
75
|
+
lib/mail/network/delivery_methods/smtp.rb
|
76
|
+
lib/mail/network/delivery_methods/test_mailer.rb
|
73
77
|
lib/mail/network/retrievable.rb
|
78
|
+
lib/mail/network/retriever_methods/imap.rb
|
79
|
+
lib/mail/network/retriever_methods/pop3.rb
|
74
80
|
lib/mail/parsers/address_lists.rb
|
75
81
|
lib/mail/parsers/address_lists.treetop
|
76
82
|
lib/mail/parsers/content_disposition.rb
|
data/README.rdoc
CHANGED
@@ -23,6 +23,11 @@ Finally, Mail has been designed with a very simple object oriented system
|
|
23
23
|
that really opens up the email messages you are parsing, if you know what
|
24
24
|
you are doing, you can fiddle with every last bit of your email directly.
|
25
25
|
|
26
|
+
== Discussion
|
27
|
+
|
28
|
+
If you want to discuss mail with like minded individuals, please subscribe to
|
29
|
+
the Google Group http://groups.google.com/group/mail-ruby
|
30
|
+
|
26
31
|
== Current Capabilities of Mail
|
27
32
|
|
28
33
|
* RFC2822 Support, Reading and Writing
|
@@ -205,7 +210,7 @@ what you are doing.
|
|
205
210
|
to 'you@test.lindsaar.net'
|
206
211
|
subject 'Here is the image you wanted'
|
207
212
|
body File.read('body.txt')
|
208
|
-
add_file '
|
213
|
+
add_file '/somefile.png'
|
209
214
|
end
|
210
215
|
|
211
216
|
or
|
@@ -219,7 +224,7 @@ or
|
|
219
224
|
to 'you@test.lindsaar.net'
|
220
225
|
subject 'Here is the image you wanted'
|
221
226
|
body File.read('body.txt')
|
222
|
-
add_file
|
227
|
+
add_file {:filename => 'somefile.png', :data => File.read('/somefile.png')}
|
223
228
|
end
|
224
229
|
|
225
230
|
mail.deliver!
|
data/lib/mail.rb
CHANGED
@@ -28,7 +28,13 @@ module Mail # :doc:
|
|
28
28
|
require File.join(dir_name, 'utilities')
|
29
29
|
require File.join(dir_name, 'configuration')
|
30
30
|
require File.join(dir_name, 'network', 'deliverable')
|
31
|
+
require File.join(dir_name, 'network', 'delivery_methods', 'smtp')
|
32
|
+
require File.join(dir_name, 'network', 'delivery_methods', 'file_delivery')
|
33
|
+
require File.join(dir_name, 'network', 'delivery_methods', 'sendmail')
|
34
|
+
require File.join(dir_name, 'network', 'delivery_methods', 'test_mailer')
|
31
35
|
require File.join(dir_name, 'network', 'retrievable')
|
36
|
+
require File.join(dir_name, 'network', 'retriever_methods', 'pop3')
|
37
|
+
require File.join(dir_name, 'network', 'retriever_methods', 'imap')
|
32
38
|
|
33
39
|
require File.join(dir_name, 'message')
|
34
40
|
require File.join(dir_name, 'part')
|
data/lib/mail/body.rb
CHANGED
data/lib/mail/configuration.rb
CHANGED
@@ -7,7 +7,11 @@ require 'singleton'
|
|
7
7
|
module Mail
|
8
8
|
|
9
9
|
# The Configuration class is a Singleton used to hold the default
|
10
|
-
# configuration for all
|
10
|
+
# configuration for all class wide configurations of Mail.
|
11
|
+
#
|
12
|
+
# This includes things like running in Test mode, the POP3, IMAP,
|
13
|
+
# SMTP, Sendmail and File delivery method information et al.
|
14
|
+
#
|
11
15
|
# See Mail.defaults for more information.
|
12
16
|
class Configuration
|
13
17
|
include Singleton
|
@@ -35,11 +39,19 @@ module Mail
|
|
35
39
|
# Mail.defaults do
|
36
40
|
# smtp '127.0.0.1', 25
|
37
41
|
# end
|
38
|
-
def smtp(*args)
|
42
|
+
def smtp(*args, &block)
|
39
43
|
if args.size > 0
|
40
|
-
|
44
|
+
host_array = [args[0], (args[1].to_i > 0 ? args[1] : 25)]
|
41
45
|
end
|
42
|
-
|
46
|
+
set_settings(Mail::SMTP, host_array, &block)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Allows you to define the delivery method for mail, defaults to SMTP
|
50
|
+
#
|
51
|
+
# This can either be a symbol (:smtp, :sendmail, :file, :test) or you can pass
|
52
|
+
# in your own delivery class, in which case this will be set.
|
53
|
+
def delivery_method(value = nil)
|
54
|
+
value ? @delivery_method = lookup_delivery_method(value) : @delivery_method ||= Mail::SMTP
|
43
55
|
end
|
44
56
|
|
45
57
|
# Allows you to specify the POP3 Server by passing the hostname
|
@@ -57,38 +69,66 @@ module Mail
|
|
57
69
|
# Mail.defaults do
|
58
70
|
# pop3 '127.0.0.1', 110
|
59
71
|
# end
|
60
|
-
def pop3(*args)
|
72
|
+
def pop3(*args, &block)
|
61
73
|
if args.size > 0
|
62
|
-
|
74
|
+
host_array = [args[0], (args[1].to_i > 0 ? args[1] : 110)]
|
63
75
|
end
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
# Pass in the username to use for POP3 or IMAP access
|
68
|
-
def user(value = nil)
|
69
|
-
value ? @user = value : @user
|
70
|
-
end
|
71
|
-
|
72
|
-
def pass(value = nil)
|
73
|
-
value ? @pass = value : @pass
|
74
|
-
end
|
75
|
-
|
76
|
-
def enable_tls
|
77
|
-
@tls = true
|
78
|
-
end
|
79
|
-
|
80
|
-
def disable_tls
|
81
|
-
@tls = false
|
76
|
+
set_settings(Mail::POP3, host_array, &block)
|
82
77
|
end
|
83
78
|
|
84
|
-
|
85
|
-
|
79
|
+
# Allows you to define the retriever method for mail, defaults to POP3
|
80
|
+
#
|
81
|
+
# This can either be a symbol (:pop3, :imap) or you can pass
|
82
|
+
# in your own retriever class, in which case this will be set.
|
83
|
+
def retriever_method(value = nil)
|
84
|
+
value ? @retriever_method = lookup_retriever_method(value) : @retriever_method ||= Mail::POP3
|
86
85
|
end
|
87
|
-
|
86
|
+
|
88
87
|
def param_encode_language(value = nil)
|
89
88
|
value ? @encode_language = value : @encode_language ||= 'en'
|
90
89
|
end
|
91
90
|
|
91
|
+
private
|
92
|
+
|
93
|
+
def set_settings(klass, host_array = nil, &block)
|
94
|
+
if host_array
|
95
|
+
klass.instance.settings do
|
96
|
+
host host_array[0]
|
97
|
+
port host_array[1]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
if block_given?
|
101
|
+
klass.instance.settings(&block)
|
102
|
+
end
|
103
|
+
klass.instance.settings(&block)
|
104
|
+
end
|
105
|
+
|
106
|
+
def lookup_delivery_method(method)
|
107
|
+
case method
|
108
|
+
when :smtp || nil
|
109
|
+
Mail::SMTP
|
110
|
+
when :sendmail
|
111
|
+
Mail::Sendmail
|
112
|
+
when :file
|
113
|
+
Mail::FileDelivery
|
114
|
+
when :test
|
115
|
+
Mail::TestMailer
|
116
|
+
else
|
117
|
+
method
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def lookup_retriever_method(method)
|
122
|
+
case method
|
123
|
+
when :pop3 || nil
|
124
|
+
Mail::POP3
|
125
|
+
# when :imap
|
126
|
+
# Mail::IMAP
|
127
|
+
else
|
128
|
+
method
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
92
132
|
end
|
93
133
|
|
94
134
|
end
|
@@ -29,6 +29,8 @@ module Mail
|
|
29
29
|
|
30
30
|
def element
|
31
31
|
@element ||= Mail::ContentTypeElement.new(value)
|
32
|
+
rescue
|
33
|
+
@element ||= Mail::ContentTypeElement.new(sanatize(value))
|
32
34
|
end
|
33
35
|
|
34
36
|
def main_type
|
@@ -102,6 +104,15 @@ module Mail
|
|
102
104
|
super
|
103
105
|
end
|
104
106
|
end
|
107
|
+
|
108
|
+
def sanatize( val )
|
109
|
+
case
|
110
|
+
when val.chomp =~ /^text$/
|
111
|
+
'text/plain'
|
112
|
+
when val =~ /([\w\d_]+\/[\w\d_]+)\s(.*)/
|
113
|
+
"#{$1}; #{$2}"
|
114
|
+
end
|
115
|
+
end
|
105
116
|
|
106
117
|
end
|
107
118
|
end
|
@@ -38,7 +38,7 @@ module Mail
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def do_decode
|
41
|
-
value.blank? ? nil : value
|
41
|
+
value.blank? ? nil : Encodings.decode_encode(value, :decode)
|
42
42
|
end
|
43
43
|
|
44
44
|
# 2.2.3. Long Header Fields
|
@@ -77,7 +77,7 @@ module Mail
|
|
77
77
|
@folded_line = []
|
78
78
|
@unfolded_line = value.clone
|
79
79
|
fold("#{name}: ".length)
|
80
|
-
folded = @folded_line.compact.join("\r\n\t")
|
80
|
+
folded = @folded_line.map { |l| l unless l.blank? }.compact.join("\r\n\t")
|
81
81
|
"#{name}: #{folded}"
|
82
82
|
end
|
83
83
|
end
|
data/lib/mail/header.rb
CHANGED
data/lib/mail/mail.rb
CHANGED
@@ -26,6 +26,17 @@ module Mail
|
|
26
26
|
# body 'This is the body'
|
27
27
|
# end
|
28
28
|
#
|
29
|
+
# Or creating via a hash (or hash like object):
|
30
|
+
#
|
31
|
+
# message = Mail.new({:to => 'mikel@test.lindsaar.net',
|
32
|
+
# 'from' => 'bob@test.lindsaar.net',
|
33
|
+
# :subject 'This is an email',
|
34
|
+
# :body 'This is the body' })
|
35
|
+
#
|
36
|
+
# Note, the hash keys can be strings or symbols, the passed in object
|
37
|
+
# does not need to be a hash, it just needs to respond to :each_pair
|
38
|
+
# and yield each key value pair.
|
39
|
+
#
|
29
40
|
# As a side note, you can also create a new email through creating
|
30
41
|
# a Mail::Message object directly and then passing in values via string,
|
31
42
|
# symbol or direct method calls. See Mail::Message for more information.
|
@@ -36,11 +47,7 @@ module Mail
|
|
36
47
|
# mail['subject'] = 'This is an email'
|
37
48
|
# mail.body = 'This is the body'
|
38
49
|
def Mail.new(*args, &block)
|
39
|
-
|
40
|
-
Mail::Message.new(args, &block)
|
41
|
-
else
|
42
|
-
Mail::Message.new(args)
|
43
|
-
end
|
50
|
+
Mail::Message.new(args, &block)
|
44
51
|
end
|
45
52
|
|
46
53
|
# Set the default configuration to send and receive emails. The defaults
|
@@ -48,19 +55,37 @@ module Mail
|
|
48
55
|
# if port values are omitted from the SMTP and POP3 method calls, then it
|
49
56
|
# is assumed to use the default ports of 25 and 110 respectively.
|
50
57
|
#
|
51
|
-
#
|
58
|
+
# You call defaults in a block, then you can set the basic host and port,
|
59
|
+
# by passing arguments, also, if the method you are using required more
|
60
|
+
# information (like pop3), then pass a block to it and call methods like
|
61
|
+
# user, pass, enable_tls etc.
|
52
62
|
#
|
53
|
-
#
|
54
|
-
# pop3(server_name, port):: Sets the POP3 server domain name and port
|
55
|
-
# user(username):: Sets the username used for POP3 sessions
|
56
|
-
# pass(password):: Sets the password used for POP3 sessions
|
63
|
+
# The arguments and block are both optional.
|
57
64
|
#
|
58
65
|
# Mail.defaults do
|
59
66
|
# smtp 'smtp.myhost.fr', 587
|
60
|
-
# pop3 'pop.myhost.fr'
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
67
|
+
# pop3 'pop.myhost.fr' do
|
68
|
+
# user 'bernardo'
|
69
|
+
# pass 'mypass'
|
70
|
+
# enable_tls
|
71
|
+
# end
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# You will also want to specify a delivery and retriever type, the defaults
|
75
|
+
# are SMTP and POP3. You set the types by passing a symbol:
|
76
|
+
#
|
77
|
+
# Mail.defaults do
|
78
|
+
# retriever_method :pop3
|
79
|
+
# delivery_method :smtp
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# The only implemented methods at the moment are :pop3, :smtp and :test
|
83
|
+
#
|
84
|
+
# You can also specify your own delivery class which must respond to :deliver!
|
85
|
+
# or a retriever class which must respond to :get_messages
|
86
|
+
#
|
87
|
+
# Mail.defaults do
|
88
|
+
# retriever_method MyOwnRetriever.new
|
64
89
|
# end
|
65
90
|
#
|
66
91
|
# Once you have set defaults, you can call Mail.deliver to send an email
|
@@ -68,6 +93,8 @@ module Mail
|
|
68
93
|
def Mail.defaults(&block)
|
69
94
|
if block_given?
|
70
95
|
Mail::Configuration.instance.defaults(&block)
|
96
|
+
else
|
97
|
+
Mail::Configuration.instance
|
71
98
|
end
|
72
99
|
end
|
73
100
|
|
@@ -75,6 +102,8 @@ module Mail
|
|
75
102
|
# configuration first before you use Mail.deliver, if you don't, an appropriate
|
76
103
|
# error will be raised telling you to.
|
77
104
|
#
|
105
|
+
# If you do not specify a delivery type, SMTP will be used.
|
106
|
+
#
|
78
107
|
# Mail.deliver do
|
79
108
|
# to 'mikel@test.lindsaar.net'
|
80
109
|
# from 'ada@test.lindsaar.net'
|
@@ -82,27 +111,46 @@ module Mail
|
|
82
111
|
# body 'Not much to say here'
|
83
112
|
# end
|
84
113
|
#
|
114
|
+
# You can also do:
|
115
|
+
#
|
116
|
+
# mail = Mail.read('email.eml')
|
117
|
+
# mail.deliver!
|
118
|
+
#
|
85
119
|
# And your email object will be created and sent.
|
86
|
-
|
87
120
|
def Mail.deliver(*args, &block)
|
88
|
-
Mail.new(args, &block)
|
121
|
+
mail = Mail.new(args, &block)
|
122
|
+
Deliverable.perform_delivery!(mail)
|
123
|
+
mail
|
89
124
|
end
|
90
125
|
|
126
|
+
# Returns all the messages on the server using the retriever method set up
|
127
|
+
# in Mail.defaults
|
91
128
|
def Mail.get_all_mail(&block)
|
92
|
-
|
129
|
+
if block_given?
|
130
|
+
Retrievable.get_messages.each do |message|
|
131
|
+
yield message
|
132
|
+
end
|
133
|
+
else
|
134
|
+
Retrievable.get_messages
|
135
|
+
end
|
93
136
|
end
|
94
137
|
|
95
138
|
def Mail.read(filename)
|
96
139
|
Mail.new(File.read(filename))
|
97
140
|
end
|
98
141
|
|
142
|
+
# Provides a store of all the emails sent
|
143
|
+
def Mail.deliveries
|
144
|
+
@@deliveries ||= []
|
145
|
+
end
|
146
|
+
|
99
147
|
protected
|
100
148
|
|
101
149
|
def Mail.random_tag
|
102
150
|
t = Time.now
|
103
151
|
sprintf('%x%x_%x%x%d%x',
|
104
152
|
t.to_i, t.tv_usec,
|
105
|
-
$$, Thread.current.object_id, Mail.uniq, rand(255))
|
153
|
+
$$, Thread.current.object_id.abs, Mail.uniq, rand(255))
|
106
154
|
end
|
107
155
|
|
108
156
|
private
|
data/lib/mail/message.rb
CHANGED
@@ -46,21 +46,43 @@ module Mail
|
|
46
46
|
|
47
47
|
include Patterns
|
48
48
|
include Utilities
|
49
|
-
include Deliverable
|
50
|
-
include Retrievable
|
51
49
|
|
52
50
|
# Creates a new Mail::Message object through .new
|
53
51
|
def initialize(*args, &block)
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
52
|
+
|
53
|
+
if args.flatten.first.respond_to?(:each_pair)
|
54
|
+
init_with_hash(args.flatten.first)
|
55
|
+
else
|
56
|
+
init_with_string(args.flatten[0].to_s.strip)
|
57
|
+
end
|
58
|
+
|
58
59
|
if block_given?
|
59
60
|
instance_eval(&block)
|
60
61
|
end
|
62
|
+
|
61
63
|
self
|
62
64
|
end
|
63
65
|
|
66
|
+
def deliver!
|
67
|
+
Deliverable.perform_delivery!(self)
|
68
|
+
end
|
69
|
+
|
70
|
+
def <=>(other)
|
71
|
+
if other.nil?
|
72
|
+
1
|
73
|
+
else
|
74
|
+
self.date <=> other.date
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def ==(other)
|
79
|
+
unless other.respond_to?(:encoded)
|
80
|
+
false
|
81
|
+
else
|
82
|
+
self.encoded == other.encoded
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
64
86
|
# Provides access to the raw source of the message as it was when it
|
65
87
|
# was instantiated. This is set at initialization and so is untouched
|
66
88
|
# by the parsers or decoder / encoders
|
@@ -133,8 +155,34 @@ module Mail
|
|
133
155
|
#
|
134
156
|
# mail.body = 'This is the body'
|
135
157
|
# mail.body #=> #<Mail::Body:0x13919c @raw_source="This is the bo...
|
158
|
+
#
|
159
|
+
# You can also reset the body of an Message object by setting body to nil
|
160
|
+
#
|
161
|
+
# Example:
|
162
|
+
#
|
163
|
+
# mail.body = 'this is the body'
|
164
|
+
# mail.body.encoded #=> 'this is the body'
|
165
|
+
# mail.body = nil
|
166
|
+
# mail.body.encoded #=> ''
|
167
|
+
#
|
168
|
+
# If you try and set the body of an email that is a multipart email, then instead
|
169
|
+
# of deleting all the parts of your email, mail will add a text/plain part to
|
170
|
+
# your email:
|
171
|
+
#
|
172
|
+
# mail.add_file 'somefilename.png'
|
173
|
+
# mail.parts.length #=> 1
|
174
|
+
# mail.body = "This is a body"
|
175
|
+
# mail.parts.length #=> 2
|
176
|
+
# mail.parts.last.content_type.content_type #=> 'This is a body'
|
136
177
|
def body=(value)
|
137
|
-
|
178
|
+
case
|
179
|
+
when value == nil
|
180
|
+
@body = Mail::Body.new('')
|
181
|
+
when @body && !@body.parts.empty?
|
182
|
+
@body << Mail::Part.new(value)
|
183
|
+
else
|
184
|
+
@body = Mail::Body.new(value)
|
185
|
+
end
|
138
186
|
end
|
139
187
|
|
140
188
|
# Returns the body of the message object. Or, if passed
|
@@ -561,8 +609,39 @@ module Mail
|
|
561
609
|
self.body << part
|
562
610
|
end
|
563
611
|
|
564
|
-
# Adds a
|
612
|
+
# Adds a file to the message. You have two options with this method, you can
|
613
|
+
# just pass in the absolute path to the file you want and Mail will read the file,
|
614
|
+
# get the filename from the path you pass in and guess the mime type, or you
|
615
|
+
# can pass in the filename as a string, and pass in the file data as a blob.
|
616
|
+
#
|
617
|
+
# Example:
|
618
|
+
#
|
619
|
+
# m = Mail.new
|
620
|
+
# m.add_file('/path/to/filename.png')
|
621
|
+
#
|
622
|
+
# or
|
623
|
+
#
|
624
|
+
# m = Mail.new
|
625
|
+
# m.add_file(:filename => 'filename.png', :data => File.read('/path/to/filename.png'))
|
626
|
+
#
|
627
|
+
# The above two alternatives will produce the same email message.
|
628
|
+
#
|
629
|
+
# Note also that if you add a file to an existing message, Mail will convert that message
|
630
|
+
# to a MIME multipart email, moving whatever plain text body you had into it's own text
|
631
|
+
# plain part.
|
632
|
+
#
|
633
|
+
# Example:
|
634
|
+
#
|
635
|
+
# m = Mail.new do
|
636
|
+
# body 'this is some text'
|
637
|
+
# end
|
638
|
+
# m.multipart? #=> false
|
639
|
+
# m.add_file('/path/to/filename.png')
|
640
|
+
# m.multipart? #=> true
|
641
|
+
# m.parts.first.content_type.content_type #=> 'text/plain'
|
642
|
+
# m.parts.last.content_type.content_type #=> 'image/png'
|
565
643
|
def add_file(options)
|
644
|
+
convert_to_multipart unless self.multipart? || self.body.decoded.blank?
|
566
645
|
add_multipart_mixed_header
|
567
646
|
if options.is_a?(Hash)
|
568
647
|
self.body << Mail::Part.new(options)
|
@@ -571,6 +650,14 @@ module Mail
|
|
571
650
|
end
|
572
651
|
end
|
573
652
|
|
653
|
+
def convert_to_multipart
|
654
|
+
text = @body.decoded
|
655
|
+
self.body = ''
|
656
|
+
text_part = Mail::Part.new({:content_type => 'text/plain;',
|
657
|
+
:body => text})
|
658
|
+
self.body << text_part
|
659
|
+
end
|
660
|
+
|
574
661
|
# Encodes the message, calls encode on all it's parts, gets an email message
|
575
662
|
# ready to send
|
576
663
|
def ready_to_send!
|
@@ -600,6 +687,25 @@ module Mail
|
|
600
687
|
raise NoMethodError, 'Can not decode an entire message, try calling #decoded on the various fields and body or parts if it is a multipart message.'
|
601
688
|
end
|
602
689
|
|
690
|
+
# Returns true if this part is an attachment
|
691
|
+
def attachment?
|
692
|
+
find_attachment
|
693
|
+
end
|
694
|
+
|
695
|
+
# Returns the attachment data if there is any
|
696
|
+
def attachment
|
697
|
+
@attachment
|
698
|
+
end
|
699
|
+
|
700
|
+
# Returns the filename of the attachment
|
701
|
+
def filename
|
702
|
+
if attachment?
|
703
|
+
attachment.filename
|
704
|
+
else
|
705
|
+
nil
|
706
|
+
end
|
707
|
+
end
|
708
|
+
|
603
709
|
private
|
604
710
|
|
605
711
|
# 2.1. General Description
|
@@ -651,17 +757,64 @@ module Mail
|
|
651
757
|
def add_multipart_mixed_header
|
652
758
|
unless header['content-type']
|
653
759
|
header['content-type'] = ContentTypeField.with_boundary('multipart/mixed').value
|
760
|
+
|
654
761
|
body.boundary = boundary
|
655
762
|
end
|
656
763
|
end
|
657
764
|
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
765
|
+
def init_with_hash(hash)
|
766
|
+
self.raw_source = ''
|
767
|
+
@header = Mail::Header.new
|
768
|
+
@body = Mail::Body.new
|
769
|
+
hash.each_pair do |k,v|
|
770
|
+
next if k.to_sym == :data
|
771
|
+
if k.to_sym == :filename
|
772
|
+
add_attachment(hash)
|
773
|
+
else
|
774
|
+
self[k] = v
|
775
|
+
end
|
663
776
|
end
|
777
|
+
end
|
778
|
+
|
779
|
+
def add_attachment(options_hash)
|
780
|
+
@attachment = Mail::Attachment.new(options_hash)
|
781
|
+
self.content_type = "#{attachment.mime_type}; filename=\"#{attachment.filename}\""
|
782
|
+
self.content_transfer_encoding = "Base64"
|
783
|
+
self.content_disposition = "attachment; filename=\"#{attachment.filename}\""
|
784
|
+
self.body = attachment.encoded
|
785
|
+
end
|
786
|
+
|
787
|
+
def init_with_string(string)
|
788
|
+
self.raw_source = string
|
789
|
+
set_envelope_header
|
790
|
+
parse_message
|
791
|
+
separate_parts if multipart?
|
792
|
+
if filename = attachment?
|
793
|
+
encoding = content_transfer_encoding.encoding if content_transfer_encoding
|
794
|
+
@attachment = Mail::Attachment.new(:filename => filename,
|
795
|
+
:data => body.to_s,
|
796
|
+
:encoding => encoding)
|
797
|
+
end
|
798
|
+
end
|
799
|
+
|
800
|
+
# Returns the filename of the attachment (if it exists) or returns nil
|
801
|
+
def find_attachment
|
802
|
+
case
|
803
|
+
when content_type && content_type.filename
|
804
|
+
filename = content_type.filename
|
805
|
+
when content_disposition && content_disposition.filename
|
806
|
+
filename = content_disposition.filename
|
807
|
+
when content_location && content_location.location
|
808
|
+
filename = content_location.location
|
809
|
+
else
|
810
|
+
filename = nil
|
811
|
+
end
|
812
|
+
filename
|
813
|
+
end
|
664
814
|
|
815
|
+
# Only POP3 is supported for now
|
816
|
+
def Message.get_all_mail(&block)
|
817
|
+
self.pop3_get_all_mail(&block)
|
665
818
|
end
|
666
819
|
|
667
820
|
end
|
@@ -1,46 +1,15 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
|
3
|
-
# Include this module to make a class "deliverable".
|
4
|
-
# It uses the defaults set in Configuration to retrieve SMTP settings.
|
5
|
-
#
|
6
|
-
# Thanks to Nicolas Fouché for this wrapper
|
7
|
-
#
|
8
2
|
module Mail
|
3
|
+
# The deliverable class provides the way mail will send an email out when you
|
4
|
+
# are using the Mail.deliver! &block command or when you call Mail.deliver!(message)
|
5
|
+
#
|
6
|
+
# The default delivery is SMTP, localhost, port 25. You can change this through the
|
7
|
+
# Mail.defaults call.s
|
9
8
|
module Deliverable
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
def deliver!(from = nil, to = nil, rfc2822 = nil)
|
14
|
-
config = Mail::Configuration.instance
|
15
|
-
if config.smtp.blank? || config.smtp[0].blank?
|
16
|
-
raise ArgumentError.new('Please call +Mail.defaults+ to set the SMTP configuration')
|
17
|
-
end
|
18
|
-
|
19
|
-
# TODO: use the "return-path" field by default instead of the "from" field ? (see ActionMailer)
|
20
|
-
from ||= self.from.addresses.first if self.respond_to?(:from) && self.from
|
21
|
-
raise ArgumentError.new('An author -from- is required to send a message') if from.blank?
|
22
|
-
to ||= self.to.addresses if self.respond_to?(:to) && self.to
|
23
|
-
raise ArgumentError.new('At least one recipient -from- is required to send a message') if to.blank?
|
24
|
-
rfc2822 ||= self.encoded if self.respond_to?(:encoded)
|
25
|
-
raise ArgumentError.new('A encoded content is required to send a message') if rfc2822.blank?
|
26
|
-
|
27
|
-
smtp = Net::SMTP.new(config.smtp[0], config.smtp[1] || 25)
|
28
|
-
if config.tls?
|
29
|
-
if OpenSSL::SSL::VERIFY_NONE.kind_of?(OpenSSL::SSL::SSLContext)
|
30
|
-
smtp.enable_tls(OpenSSL::SSL::VERIFY_NONE)
|
31
|
-
else
|
32
|
-
smtp.enable_tls
|
33
|
-
end
|
34
|
-
else
|
35
|
-
smtp.enable_starttls_auto if smtp.respond_to?(:enable_starttls_auto)
|
36
|
-
end
|
37
|
-
|
38
|
-
smtp.start(helo = 'localhost.localdomain', config.user, config.pass, authentication = :plain) do |smtp|
|
39
|
-
smtp.sendmail(rfc2822, from, to)
|
40
|
-
end
|
41
|
-
|
42
|
-
self
|
10
|
+
def self.perform_delivery!(mail)
|
11
|
+
Mail.defaults.delivery_method.deliver!(mail)
|
43
12
|
end
|
44
|
-
end
|
45
13
|
|
14
|
+
end
|
46
15
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Mail
|
2
|
+
class FileDelivery
|
3
|
+
include Singleton
|
4
|
+
|
5
|
+
def settings(&block)
|
6
|
+
if block_given?
|
7
|
+
instance_eval(&block)
|
8
|
+
end
|
9
|
+
self
|
10
|
+
end
|
11
|
+
|
12
|
+
def FileDelivery.deliver!(mail)
|
13
|
+
# To be implemented
|
14
|
+
Mail.deliveries << mail
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Mail
|
2
|
+
class SMTP
|
3
|
+
include Singleton
|
4
|
+
|
5
|
+
def settings(&block)
|
6
|
+
if block_given?
|
7
|
+
instance_eval(&block)
|
8
|
+
end
|
9
|
+
self
|
10
|
+
end
|
11
|
+
|
12
|
+
# This is the host that you will send your SMTP mails to, defaults to 'localhost'
|
13
|
+
def host(value = nil)
|
14
|
+
value ? @host = value : @host ||= 'localhost'
|
15
|
+
end
|
16
|
+
|
17
|
+
# This is the port that SMTP email get sent to, default is 25
|
18
|
+
def port(value = nil)
|
19
|
+
value ? @port = value.to_i : @port ||= 25
|
20
|
+
end
|
21
|
+
|
22
|
+
# The username to use during SMTP authentication
|
23
|
+
def user(value = nil)
|
24
|
+
value ? @user = value : @user
|
25
|
+
end
|
26
|
+
|
27
|
+
# Password to use during SMTP authentication
|
28
|
+
def pass(value = nil)
|
29
|
+
value ? @pass = value : @pass
|
30
|
+
end
|
31
|
+
|
32
|
+
# The helo domain used at the begining of an SMTP conversation,
|
33
|
+
# default is 'localhost.localdomain'
|
34
|
+
def helo(value = nil)
|
35
|
+
value ? @help = value : @helo ||= 'localhost.localdomain'
|
36
|
+
end
|
37
|
+
|
38
|
+
# Turn on TLS
|
39
|
+
def enable_tls
|
40
|
+
@tls = true
|
41
|
+
end
|
42
|
+
|
43
|
+
# Turn on TLS
|
44
|
+
def disable_tls
|
45
|
+
@tls = false
|
46
|
+
end
|
47
|
+
|
48
|
+
# TLS Enabled? Default is false
|
49
|
+
def tls?
|
50
|
+
@tls || false
|
51
|
+
end
|
52
|
+
|
53
|
+
# Send the message via SMTP.
|
54
|
+
# The from and to attributes are optional. If not set, they are retrieve from the Message.
|
55
|
+
def SMTP.deliver!(mail)
|
56
|
+
|
57
|
+
config = Mail.defaults
|
58
|
+
|
59
|
+
# TODO: use the "return-path" field by default instead of the "from" field ? (see ActionMailer)
|
60
|
+
from = mail.from.addresses.first if mail.respond_to?(:from) && mail.from
|
61
|
+
raise ArgumentError.new('An author -from- is required to send a message') if from.blank?
|
62
|
+
to ||= mail.destinations if mail.respond_to?(:destinations) && mail.destinations
|
63
|
+
raise ArgumentError.new('At least one recipient -to, cc, bcc- is required to send a message') if to.blank?
|
64
|
+
msg_str ||= mail.encoded if mail.respond_to?(:encoded)
|
65
|
+
raise ArgumentError.new('A encoded content is required to send a message') if msg_str.blank?
|
66
|
+
|
67
|
+
smtp = Net::SMTP.new(config.smtp.host, config.smtp.port)
|
68
|
+
if config.smtp.tls?
|
69
|
+
if OpenSSL::SSL::VERIFY_NONE.kind_of?(OpenSSL::SSL::SSLContext)
|
70
|
+
smtp.enable_tls(OpenSSL::SSL::VERIFY_NONE)
|
71
|
+
else
|
72
|
+
smtp.enable_tls
|
73
|
+
end
|
74
|
+
else
|
75
|
+
smtp.enable_starttls_auto if smtp.respond_to?(:enable_starttls_auto)
|
76
|
+
end
|
77
|
+
|
78
|
+
smtp.start(config.smtp.helo, config.smtp.user, config.smtp.pass, authentication = :plain) do |smtp|
|
79
|
+
smtp.sendmail(msg_str, from, to)
|
80
|
+
end
|
81
|
+
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -7,55 +7,9 @@
|
|
7
7
|
#
|
8
8
|
module Mail
|
9
9
|
module Retrievable
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
# Get all emails via POP3.
|
14
|
-
# TODO :limit option
|
15
|
-
# TODO :order option
|
16
|
-
def pop3_get_all_mail(&block)
|
17
|
-
config = Mail::Configuration.instance
|
18
|
-
if config.pop3.blank? || config.pop3[0].blank?
|
19
|
-
raise ArgumentError.new('Please call +Mail.defaults+ to set the POP3 configuration')
|
20
|
-
end
|
21
|
-
|
22
|
-
pop3_start do |pop3|
|
23
|
-
if block_given?
|
24
|
-
pop3.each_mail do |pop_mail|
|
25
|
-
yield self.new(pop_mail.pop)
|
26
|
-
end
|
27
|
-
else
|
28
|
-
emails = []
|
29
|
-
pop3.each_mail do |pop_mail|
|
30
|
-
emails << self.new(pop_mail.pop)
|
31
|
-
end
|
32
|
-
emails
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def pop3_start(config = Mail::Configuration.instance, &block)
|
41
|
-
raise ArgumentError.new("Mail::Retrievable#pop3_start takes a block") unless block_given?
|
42
|
-
|
43
|
-
pop3 = Net::POP3.new(config.pop3[0], config.pop3[1] || 110, isapop = false)
|
44
|
-
pop3.enable_ssl(verify = OpenSSL::SSL::VERIFY_NONE) if config.tls?
|
45
|
-
pop3.start(config.user, config.pass)
|
46
|
-
|
47
|
-
yield pop3
|
48
|
-
ensure
|
49
|
-
if defined?(pop3) && pop3 && pop3.started?
|
50
|
-
pop3.reset # This clears all "deleted" marks from messages.
|
51
|
-
pop3.finish
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.included(receiver)
|
58
|
-
receiver.extend ClassMethods
|
10
|
+
|
11
|
+
def self.get_messages
|
12
|
+
Mail.defaults.retriever_method.get_messages
|
59
13
|
end
|
60
14
|
|
61
15
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Mail
|
2
|
+
class POP3
|
3
|
+
include Singleton
|
4
|
+
|
5
|
+
require 'net/pop'
|
6
|
+
|
7
|
+
def settings(&block)
|
8
|
+
if block_given?
|
9
|
+
instance_eval(&block)
|
10
|
+
end
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
# This is the host that you will send your POP3 mails to, defaults to 'localhost'
|
15
|
+
def host(value = nil)
|
16
|
+
value ? @host = value : @host ||= 'localhost'
|
17
|
+
end
|
18
|
+
|
19
|
+
# This is the port that POP3 email get sent to, default is 110
|
20
|
+
def port(value = nil)
|
21
|
+
value ? @port = value.to_i : @port ||= 110
|
22
|
+
end
|
23
|
+
|
24
|
+
# The username to use during POP3 authentication
|
25
|
+
def user(value = nil)
|
26
|
+
value ? @user = value : @user
|
27
|
+
end
|
28
|
+
|
29
|
+
# Password to use during POP3 authentication
|
30
|
+
def pass(value = nil)
|
31
|
+
value ? @pass = value : @pass
|
32
|
+
end
|
33
|
+
|
34
|
+
# Turn on TLS
|
35
|
+
def enable_tls
|
36
|
+
@tls = true
|
37
|
+
end
|
38
|
+
|
39
|
+
# Turn on TLS
|
40
|
+
def disable_tls
|
41
|
+
@tls = false
|
42
|
+
end
|
43
|
+
|
44
|
+
# TLS Enabled? Default is false
|
45
|
+
def tls?
|
46
|
+
@tls || false
|
47
|
+
end
|
48
|
+
|
49
|
+
# Get all emails via POP3.
|
50
|
+
# TODO :limit option
|
51
|
+
# TODO :order option
|
52
|
+
def POP3.get_messages(&block)
|
53
|
+
config = Mail.defaults
|
54
|
+
if config.pop3.host.blank? || config.pop3.port.blank?
|
55
|
+
raise ArgumentError.new('Please call +Mail.defaults+ to set the POP3 configuration')
|
56
|
+
end
|
57
|
+
|
58
|
+
start do |pop3|
|
59
|
+
if block_given?
|
60
|
+
pop3.each_mail do |pop_mail|
|
61
|
+
yield Mail.new(pop_mail.pop)
|
62
|
+
end
|
63
|
+
else
|
64
|
+
emails = []
|
65
|
+
pop3.each_mail do |pop_mail|
|
66
|
+
emails << Mail.new(pop_mail.pop)
|
67
|
+
end
|
68
|
+
emails
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def POP3.start(config = Mail::Configuration.instance, &block)
|
77
|
+
raise ArgumentError.new("Mail::Retrievable#pop3_start takes a block") unless block_given?
|
78
|
+
|
79
|
+
pop3 = Net::POP3.new(config.pop3.host, config.pop3.port, isapop = false)
|
80
|
+
pop3.enable_ssl(verify = OpenSSL::SSL::VERIFY_NONE) if config.pop3.tls?
|
81
|
+
pop3.start(config.pop3.user, config.pop3.pass)
|
82
|
+
|
83
|
+
yield pop3
|
84
|
+
ensure
|
85
|
+
if defined?(pop3) && pop3 && pop3.started?
|
86
|
+
pop3.reset # This clears all "deleted" marks from messages.
|
87
|
+
pop3.finish
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
data/lib/mail/parsers/rfc2822.rb
CHANGED
@@ -961,6 +961,53 @@ module Mail
|
|
961
961
|
r0
|
962
962
|
end
|
963
963
|
|
964
|
+
def _nt_mtext
|
965
|
+
start_index = index
|
966
|
+
if node_cache[:mtext].has_key?(index)
|
967
|
+
cached = node_cache[:mtext][index]
|
968
|
+
@index = cached.interval.end if cached
|
969
|
+
return cached
|
970
|
+
end
|
971
|
+
|
972
|
+
s0, i0 = [], index
|
973
|
+
loop do
|
974
|
+
i1 = index
|
975
|
+
r2 = _nt_atext
|
976
|
+
if r2
|
977
|
+
r1 = r2
|
978
|
+
else
|
979
|
+
if has_terminal?(".", false, index)
|
980
|
+
r3 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
981
|
+
@index += 1
|
982
|
+
else
|
983
|
+
terminal_parse_failure(".")
|
984
|
+
r3 = nil
|
985
|
+
end
|
986
|
+
if r3
|
987
|
+
r1 = r3
|
988
|
+
else
|
989
|
+
@index = i1
|
990
|
+
r1 = nil
|
991
|
+
end
|
992
|
+
end
|
993
|
+
if r1
|
994
|
+
s0 << r1
|
995
|
+
else
|
996
|
+
break
|
997
|
+
end
|
998
|
+
end
|
999
|
+
if s0.empty?
|
1000
|
+
@index = i0
|
1001
|
+
r0 = nil
|
1002
|
+
else
|
1003
|
+
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
|
1004
|
+
end
|
1005
|
+
|
1006
|
+
node_cache[:mtext][start_index] = r0
|
1007
|
+
|
1008
|
+
r0
|
1009
|
+
end
|
1010
|
+
|
964
1011
|
module Atom0
|
965
1012
|
end
|
966
1013
|
|
@@ -1118,6 +1165,35 @@ module Mail
|
|
1118
1165
|
r0
|
1119
1166
|
end
|
1120
1167
|
|
1168
|
+
def _nt_message_id_text
|
1169
|
+
start_index = index
|
1170
|
+
if node_cache[:message_id_text].has_key?(index)
|
1171
|
+
cached = node_cache[:message_id_text][index]
|
1172
|
+
@index = cached.interval.end if cached
|
1173
|
+
return cached
|
1174
|
+
end
|
1175
|
+
|
1176
|
+
s0, i0 = [], index
|
1177
|
+
loop do
|
1178
|
+
r1 = _nt_mtext
|
1179
|
+
if r1
|
1180
|
+
s0 << r1
|
1181
|
+
else
|
1182
|
+
break
|
1183
|
+
end
|
1184
|
+
end
|
1185
|
+
if s0.empty?
|
1186
|
+
@index = i0
|
1187
|
+
r0 = nil
|
1188
|
+
else
|
1189
|
+
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
|
1190
|
+
end
|
1191
|
+
|
1192
|
+
node_cache[:message_id_text][start_index] = r0
|
1193
|
+
|
1194
|
+
r0
|
1195
|
+
end
|
1196
|
+
|
1121
1197
|
module DotAtomText0
|
1122
1198
|
def domain_text
|
1123
1199
|
elements[0]
|
@@ -4378,7 +4454,7 @@ module Mail
|
|
4378
4454
|
end
|
4379
4455
|
|
4380
4456
|
i0 = index
|
4381
|
-
r1 =
|
4457
|
+
r1 = _nt_message_id_text
|
4382
4458
|
if r1
|
4383
4459
|
r0 = r1
|
4384
4460
|
else
|
@@ -84,6 +84,10 @@ module Mail
|
|
84
84
|
"|" / "}" /
|
85
85
|
"~"
|
86
86
|
end
|
87
|
+
|
88
|
+
rule mtext
|
89
|
+
(atext / ".")+
|
90
|
+
end
|
87
91
|
|
88
92
|
rule atom
|
89
93
|
CFWS? atext+ CFWS?
|
@@ -97,6 +101,10 @@ module Mail
|
|
97
101
|
CFWS? local_dot_atom_text CFWS?
|
98
102
|
end
|
99
103
|
|
104
|
+
rule message_id_text
|
105
|
+
mtext+
|
106
|
+
end
|
107
|
+
|
100
108
|
rule dot_atom_text
|
101
109
|
(domain_text "."?)+
|
102
110
|
end
|
@@ -360,7 +368,7 @@ module Mail
|
|
360
368
|
end
|
361
369
|
|
362
370
|
rule id_left
|
363
|
-
|
371
|
+
message_id_text / no_fold_quote / obs_id_left
|
364
372
|
end
|
365
373
|
|
366
374
|
rule id_right
|
data/lib/mail/part.rb
CHANGED
@@ -2,25 +2,6 @@
|
|
2
2
|
module Mail
|
3
3
|
class Part < Message
|
4
4
|
|
5
|
-
def initialize(*args, &block)
|
6
|
-
if args.flatten[0].is_a?(Hash)
|
7
|
-
options_hash = args.flatten[0]
|
8
|
-
super('') # Make an empty message, we are dealing with an attachment
|
9
|
-
@attachment = Mail::Attachment.new(options_hash)
|
10
|
-
self.content_type = "#{attachment.mime_type}; filename=\"#{attachment.filename}\""
|
11
|
-
self.content_transfer_encoding = "Base64"
|
12
|
-
self.content_disposition = "attachment; filename=\"#{attachment.filename}\""
|
13
|
-
self.body = attachment.encoded
|
14
|
-
else
|
15
|
-
super
|
16
|
-
if filename = attachment?
|
17
|
-
@attachment = Mail::Attachment.new(:filename => filename,
|
18
|
-
:data => body.to_s,
|
19
|
-
:encoding => content_transfer_encoding.encoding)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
5
|
# Creates a new empty Content-ID field and inserts it in the correct order
|
25
6
|
# into the Header. The ContentIdField object will automatically generate
|
26
7
|
# a unique content ID if you try and encode it or output it to_s without
|
@@ -31,25 +12,6 @@ module Mail
|
|
31
12
|
header['content-id'] = content_id_val
|
32
13
|
end
|
33
14
|
|
34
|
-
# Returns true if this part is an attachment
|
35
|
-
def attachment?
|
36
|
-
find_attachment
|
37
|
-
end
|
38
|
-
|
39
|
-
# Returns the attachment data if there is any
|
40
|
-
def attachment
|
41
|
-
@attachment
|
42
|
-
end
|
43
|
-
|
44
|
-
# Returns the filename of the attachment
|
45
|
-
def filename
|
46
|
-
if attachment?
|
47
|
-
attachment.filename
|
48
|
-
else
|
49
|
-
nil
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
15
|
# Returns true if the part has a content ID field, the field may or may
|
54
16
|
# not have a value, but the field exists or not.
|
55
17
|
def has_content_id?
|
@@ -115,21 +77,6 @@ module Mail
|
|
115
77
|
@delivery_status_data ||= Header.new(body.to_s.gsub("\r\n\r\n", "\r\n"))
|
116
78
|
end
|
117
79
|
|
118
|
-
# Returns the filename of the attachment (if it exists) or returns nil
|
119
|
-
def find_attachment
|
120
|
-
case
|
121
|
-
when content_type && content_type.filename
|
122
|
-
filename = content_type.filename
|
123
|
-
when content_disposition && content_disposition.filename
|
124
|
-
filename = content_disposition.filename
|
125
|
-
when content_location && content_location.location
|
126
|
-
filename = content_location.location
|
127
|
-
else
|
128
|
-
filename = nil
|
129
|
-
end
|
130
|
-
filename
|
131
|
-
end
|
132
|
-
|
133
80
|
end
|
134
81
|
|
135
82
|
end
|
data/lib/mail/patterns.rb
CHANGED
data/lib/mail/utilities.rb
CHANGED
@@ -25,9 +25,13 @@ module Mail
|
|
25
25
|
# in double quotes, otherwise returns the string unmodified
|
26
26
|
def quote_phrase( str )
|
27
27
|
if RUBY_VERSION >= '1.9'
|
28
|
-
|
29
|
-
|
30
|
-
(PHRASE_UNSAFE ===
|
28
|
+
original_encoding = str.encoding
|
29
|
+
str.force_encoding('ASCII-8BIT')
|
30
|
+
if (PHRASE_UNSAFE === str)
|
31
|
+
dquote(str).force_encoding(original_encoding)
|
32
|
+
else
|
33
|
+
str.force_encoding(original_encoding)
|
34
|
+
end
|
31
35
|
else
|
32
36
|
(PHRASE_UNSAFE === str) ? dquote(str) : str
|
33
37
|
end
|
data/lib/mail/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mail
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mikel Lindsaar
|
@@ -133,7 +133,13 @@ files:
|
|
133
133
|
- ./lib/mail/mail.rb
|
134
134
|
- ./lib/mail/message.rb
|
135
135
|
- ./lib/mail/network/deliverable.rb
|
136
|
+
- ./lib/mail/network/delivery_methods/file_delivery.rb
|
137
|
+
- ./lib/mail/network/delivery_methods/sendmail.rb
|
138
|
+
- ./lib/mail/network/delivery_methods/smtp.rb
|
139
|
+
- ./lib/mail/network/delivery_methods/test_mailer.rb
|
136
140
|
- ./lib/mail/network/retrievable.rb
|
141
|
+
- ./lib/mail/network/retriever_methods/imap.rb
|
142
|
+
- ./lib/mail/network/retriever_methods/pop3.rb
|
137
143
|
- ./lib/mail/parsers/address_lists.rb
|
138
144
|
- ./lib/mail/parsers/address_lists.treetop
|
139
145
|
- ./lib/mail/parsers/content_disposition.rb
|