mail 1.6.0 → 2.0.3
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 +37 -0
- data/README.rdoc +9 -10
- data/Rakefile +1 -1
- data/lib/mail.rb +3 -3
- data/lib/mail/attachments_list.rb +76 -0
- data/lib/mail/body.rb +16 -16
- data/lib/mail/configuration.rb +35 -111
- data/lib/mail/encodings/encodings.rb +4 -0
- data/lib/mail/fields/common/address_container.rb +16 -0
- data/lib/mail/fields/common/common_address.rb +28 -3
- data/lib/mail/fields/return_path_field.rb +4 -0
- data/lib/mail/mail.rb +69 -57
- data/lib/mail/message.rb +169 -58
- data/lib/mail/network/delivery_methods/file_delivery.rb +32 -10
- data/lib/mail/network/delivery_methods/sendmail.rb +52 -14
- data/lib/mail/network/delivery_methods/smtp.rb +85 -68
- data/lib/mail/network/delivery_methods/test_mailer.rb +7 -2
- data/lib/mail/network/retriever_methods/imap.rb +7 -6
- data/lib/mail/network/retriever_methods/pop3.rb +48 -73
- data/lib/mail/parts_list.rb +34 -0
- data/lib/mail/vendor/treetop-1.4.3/examples/lambda_calculus/arithmetic.rb +1 -1
- data/lib/mail/vendor/treetop-1.4.3/examples/lambda_calculus/lambda_calculus.rb +1 -1
- data/lib/mail/vendor/treetop-1.4.3/lib/treetop/compiler/metagrammar.rb +1 -1
- data/lib/mail/vendor/treetop.rb +1 -1
- data/lib/mail/version.rb +3 -3
- metadata +5 -5
- data/lib/mail/attachment.rb +0 -107
- data/lib/mail/network/deliverable.rb +0 -15
- data/lib/mail/network/retrievable.rb +0 -19
@@ -1,17 +1,39 @@
|
|
1
1
|
module Mail
|
2
|
+
|
3
|
+
# FileDelivery class delivers emails into multiple files based on the destination
|
4
|
+
# address. Each file is appended to if it already exists.
|
5
|
+
#
|
6
|
+
# So if you have an email going to fred@test, bob@test, joe@anothertest, and you
|
7
|
+
# set your location path to ~/tmp/mails then FileDelivery will create ~/tmp/mails
|
8
|
+
# if it does not exist, and put one copy of the email in three files, called
|
9
|
+
# "fred@test", "bob@test" and "joe@anothertest"
|
10
|
+
#
|
11
|
+
# Make sure the path you specify with :location is writable by the Ruby process
|
12
|
+
# running Mail.
|
2
13
|
class FileDelivery
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
14
|
+
|
15
|
+
if RUBY_VERSION >= '1.9.1'
|
16
|
+
require 'fileutils'
|
17
|
+
else
|
18
|
+
require 'ftools'
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(values)
|
22
|
+
self.settings = { :location => './mails' }.merge!(values)
|
10
23
|
end
|
11
24
|
|
12
|
-
|
13
|
-
|
14
|
-
|
25
|
+
attr_accessor :settings
|
26
|
+
|
27
|
+
def deliver!(mail)
|
28
|
+
if ::File.respond_to?(:makedirs)
|
29
|
+
::File.makedirs settings[:location]
|
30
|
+
else
|
31
|
+
::FileUtils.mkdir_p settings[:location]
|
32
|
+
end
|
33
|
+
|
34
|
+
mail.destinations.uniq.each do |to|
|
35
|
+
::File.open(::File.join(settings[:location], to), 'a') { |f| "#{f.write(mail.encoded)}\r\n\r\n" }
|
36
|
+
end
|
15
37
|
end
|
16
38
|
|
17
39
|
end
|
@@ -1,22 +1,60 @@
|
|
1
1
|
module Mail
|
2
|
+
# A delivery method implementation which sends via sendmail.
|
3
|
+
#
|
4
|
+
# To use this, first find out where the sendmail binary is on your computer,
|
5
|
+
# if you are on a mac or unix box, it is usually in /usr/sbin/sendmail, this will
|
6
|
+
# be your sendmail location.
|
7
|
+
#
|
8
|
+
# Mail.defaults do
|
9
|
+
# delivery_method :sendmail
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# Or if your sendmail binary is not at '/usr/sbin/sendmail'
|
13
|
+
#
|
14
|
+
# Mail.defaults do
|
15
|
+
# delivery_method :sendmail, :location => '/absolute/path/to/your/sendmail'
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# Then just deliver the email as normal:
|
19
|
+
#
|
20
|
+
# Mail.deliver do
|
21
|
+
# to 'mikel@test.lindsaar.net'
|
22
|
+
# from 'ada@test.lindsaar.net'
|
23
|
+
# subject 'testing sendmail'
|
24
|
+
# body 'testing sendmail'
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# Or by calling deliver on a Mail message
|
28
|
+
#
|
29
|
+
# mail = Mail.new do
|
30
|
+
# to 'mikel@test.lindsaar.net'
|
31
|
+
# from 'ada@test.lindsaar.net'
|
32
|
+
# subject 'testing sendmail'
|
33
|
+
# body 'testing sendmail'
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# mail.deliver!
|
2
37
|
class Sendmail
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
instance_eval(&block)
|
8
|
-
end
|
9
|
-
self
|
38
|
+
|
39
|
+
def initialize(values)
|
40
|
+
self.settings = { :location => '/usr/sbin/sendmail',
|
41
|
+
:arguments => '-i -t' }.merge(values)
|
10
42
|
end
|
43
|
+
|
44
|
+
attr_accessor :settings
|
11
45
|
|
12
|
-
def
|
13
|
-
|
14
|
-
|
46
|
+
def deliver!(mail)
|
47
|
+
envelope_from = mail.return_path || mail.sender || mail.from_addrs.first
|
48
|
+
return_path = "-f \"#{envelope_from}\"" if envelope_from
|
15
49
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
50
|
+
arguments = [settings[:arguments], return_path].compact.join(" ")
|
51
|
+
|
52
|
+
Sendmail.call(settings[:location], arguments, mail.destinations.join(" "), mail)
|
53
|
+
end
|
54
|
+
|
55
|
+
def Sendmail.call(path, arguments, destinations, mail)
|
56
|
+
IO.popen("#{path} #{arguments} #{destinations}", "w+") do |io|
|
57
|
+
io.puts mail.encoded.to_lf
|
20
58
|
io.flush
|
21
59
|
end
|
22
60
|
end
|
@@ -1,87 +1,104 @@
|
|
1
1
|
module Mail
|
2
|
+
# == Sending Email with SMTP
|
3
|
+
#
|
4
|
+
# Mail allows you to send emails using SMTP. This is done by wrapping Net::SMTP in
|
5
|
+
# an easy to use manner.
|
6
|
+
#
|
7
|
+
# === Sending via SMTP server on Localhost
|
8
|
+
#
|
9
|
+
# Sending locally (to a postfix or sendmail server running on localhost) requires
|
10
|
+
# no special setup. Just to Mail.deliver &block or message.deliver! and it will
|
11
|
+
# be sent in this method.
|
12
|
+
#
|
13
|
+
# === Sending via MobileMe
|
14
|
+
#
|
15
|
+
# Mail.defaults do
|
16
|
+
# delivery_method :smtp, { :address => "smtp.me.com",
|
17
|
+
# :port => 587,
|
18
|
+
# :domain => 'your.host.name',
|
19
|
+
# :user_name => '<username>',
|
20
|
+
# :password => '<password>',
|
21
|
+
# :authentication => 'plain',
|
22
|
+
# :enable_starttls_auto => true }
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# === Sending via GMail
|
26
|
+
#
|
27
|
+
# Mail.defaults do
|
28
|
+
# delivery_method :smtp, { :address => "smtp.gmail.com",
|
29
|
+
# :port => 587,
|
30
|
+
# :domain => 'baci.lindsaar.net',
|
31
|
+
# :user_name => 'raasdnil',
|
32
|
+
# :password => 'g333ma11',
|
33
|
+
# :authentication => 'plain',
|
34
|
+
# :enable_starttls_auto => true }
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# === Others
|
38
|
+
#
|
39
|
+
# Feel free to send me other examples that were tricky
|
40
|
+
#
|
41
|
+
# === Delivering the email
|
42
|
+
#
|
43
|
+
# Once you have the settings right, sending the email is done by:
|
44
|
+
#
|
45
|
+
# Mail.deliver do
|
46
|
+
# to 'mikel@test.lindsaar.net'
|
47
|
+
# from 'ada@test.lindsaar.net'
|
48
|
+
# subject 'testing sendmail'
|
49
|
+
# body 'testing sendmail'
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# Or by calling deliver on a Mail message
|
53
|
+
#
|
54
|
+
# mail = Mail.new do
|
55
|
+
# to 'mikel@test.lindsaar.net'
|
56
|
+
# from 'ada@test.lindsaar.net'
|
57
|
+
# subject 'testing sendmail'
|
58
|
+
# body 'testing sendmail'
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# mail.deliver!
|
2
62
|
class SMTP
|
3
|
-
include Singleton
|
4
|
-
|
5
|
-
def initialize
|
6
|
-
@user = nil
|
7
|
-
@pass = nil
|
8
|
-
@tls = false
|
9
|
-
end
|
10
|
-
|
11
|
-
def settings(&block)
|
12
|
-
if block_given?
|
13
|
-
instance_eval(&block)
|
14
|
-
end
|
15
|
-
self
|
16
|
-
end
|
17
|
-
|
18
|
-
# This is the host that you will send your SMTP mails to, defaults to 'localhost'
|
19
|
-
def host(value = nil)
|
20
|
-
value ? @host = value : @host ||= 'localhost'
|
21
|
-
end
|
22
63
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
64
|
+
def initialize(values)
|
65
|
+
self.settings = { :address => "localhost",
|
66
|
+
:port => 25,
|
67
|
+
:domain => 'localhost.localdomain',
|
68
|
+
:user_name => nil,
|
69
|
+
:password => nil,
|
70
|
+
:authentication => nil,
|
71
|
+
:enable_starttls_auto => true }.merge!(values)
|
31
72
|
end
|
32
73
|
|
33
|
-
|
34
|
-
def pass(value = nil)
|
35
|
-
value ? @pass = value : @pass
|
36
|
-
end
|
37
|
-
|
38
|
-
# The helo domain used at the begining of an SMTP conversation,
|
39
|
-
# default is 'localhost.localdomain'
|
40
|
-
def helo(value = nil)
|
41
|
-
value ? @helo = value : @helo ||= 'localhost.localdomain'
|
42
|
-
end
|
43
|
-
|
44
|
-
# Turn on TLS
|
45
|
-
def enable_tls
|
46
|
-
@tls = true
|
47
|
-
end
|
48
|
-
|
49
|
-
# Turn off TLS
|
50
|
-
def disable_tls
|
51
|
-
@tls = false
|
52
|
-
end
|
53
|
-
|
54
|
-
# TLS Enabled? Default is false
|
55
|
-
def tls?
|
56
|
-
@tls || false
|
57
|
-
end
|
74
|
+
attr_accessor :settings
|
58
75
|
|
59
76
|
# Send the message via SMTP.
|
60
77
|
# The from and to attributes are optional. If not set, they are retrieve from the Message.
|
61
|
-
def
|
62
|
-
|
63
|
-
config = Mail.defaults
|
78
|
+
def deliver!(mail)
|
64
79
|
|
65
80
|
# Set the envelope from to be either the return-path, the sender or the first from address
|
66
81
|
envelope_from = mail.return_path || mail.sender || mail.from_addrs.first
|
67
|
-
|
82
|
+
if envelope_from.blank?
|
83
|
+
raise ArgumentError.new('A sender (Return-Path, Sender or From) required to send a message')
|
84
|
+
end
|
85
|
+
|
68
86
|
destinations ||= mail.destinations if mail.respond_to?(:destinations) && mail.destinations
|
69
|
-
|
87
|
+
if destinations.blank?
|
88
|
+
raise ArgumentError.new('At least one recipient (To, Cc or Bcc) is required to send a message')
|
89
|
+
end
|
90
|
+
|
70
91
|
message ||= mail.encoded if mail.respond_to?(:encoded)
|
71
|
-
|
92
|
+
if message.blank?
|
93
|
+
raise ArgumentError.new('A encoded content is required to send a message')
|
94
|
+
end
|
72
95
|
|
73
|
-
smtp = Net::SMTP.new(
|
74
|
-
if
|
75
|
-
if
|
76
|
-
smtp.enable_tls(OpenSSL::SSL::VERIFY_NONE)
|
77
|
-
else
|
78
|
-
smtp.enable_tls
|
79
|
-
end
|
80
|
-
else
|
81
|
-
smtp.enable_starttls_auto if smtp.respond_to?(:enable_starttls_auto)
|
96
|
+
smtp = Net::SMTP.new(settings[:address], settings[:port])
|
97
|
+
if settings[:enable_starttls_auto]
|
98
|
+
smtp.enable_starttls_auto if smtp.respond_to?(:enable_starttls_auto)
|
82
99
|
end
|
83
100
|
|
84
|
-
smtp.start(
|
101
|
+
smtp.start(settings[:domain], settings[:user_name], settings[:password], settings[:authentication]) do |smtp|
|
85
102
|
smtp.sendmail(message, envelope_from, destinations)
|
86
103
|
end
|
87
104
|
|
@@ -1,14 +1,19 @@
|
|
1
1
|
module Mail
|
2
2
|
class TestMailer
|
3
|
-
|
3
|
+
|
4
|
+
def initialize(values)
|
5
|
+
@settings = {}
|
6
|
+
end
|
4
7
|
|
8
|
+
attr_accessor :settings
|
9
|
+
|
5
10
|
# The Test Mailer provides a mail delivery method that does not hit
|
6
11
|
# your network or mail agent, in this way you can send all the emails
|
7
12
|
# you want and they will just be appended to Mail.deliveries
|
8
13
|
#
|
9
14
|
# See the README under Using Mail with Testing or Spec'ing Libraries
|
10
15
|
# for more information.
|
11
|
-
def
|
16
|
+
def deliver!(mail)
|
12
17
|
Mail.deliveries << mail
|
13
18
|
end
|
14
19
|
|
@@ -1,12 +1,13 @@
|
|
1
1
|
module Mail
|
2
2
|
class IMAP
|
3
|
-
include Singleton
|
4
3
|
|
5
|
-
def
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
def initialize(values)
|
5
|
+
self.settings = { :address => "localhost",
|
6
|
+
:port => 110,
|
7
|
+
:user_name => nil,
|
8
|
+
:password => nil,
|
9
|
+
:authentication => nil,
|
10
|
+
:enable_ssl => false }.merge!(values)
|
10
11
|
end
|
11
12
|
|
12
13
|
def IMAP.get_messages(&block)
|
@@ -1,65 +1,49 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
# The Pop3 retriever allows to get the last, first or all emails from a Pop3 server.
|
4
|
-
# Each email retrieved (RFC2822) is given as an instance of +Message+.
|
5
|
-
#
|
6
|
-
# While being retrieved, emails can be yielded if a block is given.
|
7
|
-
#
|
8
|
-
# This module uses the defaults set in Configuration to retrieve POP3 settings.
|
9
|
-
#
|
10
3
|
module Mail
|
4
|
+
# The Pop3 retriever allows to get the last, first or all emails from a POP3 server.
|
5
|
+
# Each email retrieved (RFC2822) is given as an instance of +Message+.
|
6
|
+
#
|
7
|
+
# While being retrieved, emails can be yielded if a block is given.
|
8
|
+
#
|
9
|
+
# === Example of retrieving Emails from GMail:
|
10
|
+
#
|
11
|
+
# Mail.defaults do
|
12
|
+
# retriever_method :pop3, { :address => "pop.gmail.com",
|
13
|
+
# :port => 995,
|
14
|
+
# :user_name => '<username>',
|
15
|
+
# :password => '<password>',
|
16
|
+
# :enable_ssl => true }
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# Mail.all #=> Returns an array of all emails
|
20
|
+
# Mail.first #=> Returns the first unread email
|
21
|
+
# Mail.last #=> Returns the first unread email
|
22
|
+
#
|
23
|
+
# You can also pass options into Mail.find to locate an email in your pop mailbox
|
24
|
+
# with the following options:
|
25
|
+
#
|
26
|
+
# what: last or first emails. The default is :first.
|
27
|
+
# order: order of emails returned. Possible values are :asc or :desc. Default value is :asc.
|
28
|
+
# count: number of emails to retrieve. The default value is 10. A value of 1 returns an
|
29
|
+
# instance of Message, not an array of Message instances.
|
30
|
+
#
|
31
|
+
# Mail.find(:what => :first, :count => 10, :order => :asc)
|
32
|
+
# #=> Returns the first 10 emails in ascending order
|
33
|
+
#
|
11
34
|
class POP3
|
12
|
-
include Singleton
|
13
|
-
|
14
|
-
def initialize
|
15
|
-
@user = nil
|
16
|
-
@pass = nil
|
17
|
-
@tls = false
|
18
|
-
end
|
19
|
-
|
20
35
|
require 'net/pop'
|
21
|
-
|
22
|
-
def settings(&block)
|
23
|
-
if block_given?
|
24
|
-
instance_eval(&block)
|
25
|
-
end
|
26
|
-
self
|
27
|
-
end
|
28
|
-
|
29
|
-
# This is the host that you will send your POP3 mails to, defaults to 'localhost'
|
30
|
-
def host(value = nil)
|
31
|
-
value ? @host = value : @host ||= 'localhost'
|
32
|
-
end
|
33
36
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
value ? @user = value : @user
|
37
|
+
def initialize(values)
|
38
|
+
self.settings = { :address => "localhost",
|
39
|
+
:port => 110,
|
40
|
+
:user_name => nil,
|
41
|
+
:password => nil,
|
42
|
+
:authentication => nil,
|
43
|
+
:enable_ssl => false }.merge!(values)
|
42
44
|
end
|
43
45
|
|
44
|
-
|
45
|
-
def pass(value = nil)
|
46
|
-
value ? @pass = value : @pass
|
47
|
-
end
|
48
|
-
|
49
|
-
# Turn on TLS
|
50
|
-
def enable_tls
|
51
|
-
@tls = true
|
52
|
-
end
|
53
|
-
|
54
|
-
# Turn on TLS
|
55
|
-
def disable_tls
|
56
|
-
@tls = false
|
57
|
-
end
|
58
|
-
|
59
|
-
# TLS Enabled? Default is false
|
60
|
-
def tls?
|
61
|
-
@tls || false
|
62
|
-
end
|
46
|
+
attr_accessor :settings
|
63
47
|
|
64
48
|
# Get the oldest received email(s)
|
65
49
|
#
|
@@ -67,7 +51,7 @@ module Mail
|
|
67
51
|
# count: number of emails to retrieve. The default value is 1.
|
68
52
|
# order: order of emails returned. Possible values are :asc or :desc. Default value is :asc.
|
69
53
|
#
|
70
|
-
def
|
54
|
+
def first(options = {}, &block)
|
71
55
|
options ||= {}
|
72
56
|
options[:what] = :first
|
73
57
|
options[:count] ||= 1
|
@@ -80,7 +64,7 @@ module Mail
|
|
80
64
|
# count: number of emails to retrieve. The default value is 1.
|
81
65
|
# order: order of emails returned. Possible values are :asc or :desc. Default value is :asc.
|
82
66
|
#
|
83
|
-
def
|
67
|
+
def last(options = {}, &block)
|
84
68
|
options ||= {}
|
85
69
|
options[:what] = :last
|
86
70
|
options[:count] ||= 1
|
@@ -92,7 +76,7 @@ module Mail
|
|
92
76
|
# Possible options:
|
93
77
|
# order: order of emails returned. Possible values are :asc or :desc. Default value is :asc.
|
94
78
|
#
|
95
|
-
def
|
79
|
+
def all(options = {}, &block)
|
96
80
|
options ||= {}
|
97
81
|
options[:count] = :all
|
98
82
|
find(options, &block)
|
@@ -106,8 +90,7 @@ module Mail
|
|
106
90
|
# count: number of emails to retrieve. The default value is 10. A value of 1 returns an
|
107
91
|
# instance of Message, not an array of Message instances.
|
108
92
|
#
|
109
|
-
def
|
110
|
-
validate_configuration
|
93
|
+
def find(options = {}, &block)
|
111
94
|
options = validate_options(options)
|
112
95
|
|
113
96
|
start do |pop3|
|
@@ -136,31 +119,23 @@ module Mail
|
|
136
119
|
end
|
137
120
|
|
138
121
|
private
|
139
|
-
|
140
|
-
# Ensure that the POP3 configuration is set
|
141
|
-
def POP3.validate_configuration
|
142
|
-
config = Mail::Configuration.instance
|
143
|
-
if config.pop3.host.blank? || config.pop3.port.blank?
|
144
|
-
raise ArgumentError.new('Please call +Mail.defaults+ to set the POP3 configuration')
|
145
|
-
end
|
146
|
-
end
|
147
122
|
|
148
123
|
# Set default options
|
149
|
-
def
|
124
|
+
def validate_options(options)
|
150
125
|
options ||= {}
|
151
126
|
options[:count] ||= 10
|
152
127
|
options[:order] ||= :asc
|
153
|
-
options[:what]
|
128
|
+
options[:what] ||= :first
|
154
129
|
options
|
155
130
|
end
|
156
131
|
|
157
132
|
# Start a POP3 session and ensures that it will be closed in any case.
|
158
|
-
def
|
133
|
+
def start(config = Mail::Configuration.instance, &block)
|
159
134
|
raise ArgumentError.new("Mail::Retrievable#pop3_start takes a block") unless block_given?
|
160
135
|
|
161
|
-
pop3 = Net::POP3.new(
|
162
|
-
pop3.enable_ssl(verify = OpenSSL::SSL::VERIFY_NONE) if
|
163
|
-
pop3.start(
|
136
|
+
pop3 = Net::POP3.new(settings[:address], settings[:port], isapop = false)
|
137
|
+
pop3.enable_ssl(verify = OpenSSL::SSL::VERIFY_NONE) if settings[:enable_ssl]
|
138
|
+
pop3.start(settings[:user_name], settings[:password])
|
164
139
|
|
165
140
|
yield pop3
|
166
141
|
ensure
|