fast-mailer 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -3,7 +3,7 @@ FastMailer
3
3
 
4
4
  FastMailer is a collection of helpers that aims to help with sending email.
5
5
  Specifically, it allows for convenient configuration and better throughput
6
- when sending multiple mails.
6
+ when sending multiple mails using SMTP.
7
7
 
8
8
 
9
9
  Configuration
@@ -55,6 +55,17 @@ email, we can send multiple emails using a single connection.
55
55
  end
56
56
 
57
57
 
58
+ Testing
59
+ -------
60
+
61
+ To enable testing, first run
62
+
63
+ FastMailer.test_mode = true
64
+
65
+ This will cause FastMailer::SMTP to use FastMailer::MockSMTP rather than Net::SMTP.
66
+ You can then find your sent emails in FastMailer::MockSMTP.deliveries.
67
+
68
+
58
69
  Coming features
59
70
  ---------------
60
71
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.1.0
data/bin/autotest ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'autotest' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", __FILE__)
10
+
11
+ require 'rubygems'
12
+ require 'bundler/setup'
13
+
14
+ load Gem.bin_path('autotest', 'autotest')
data/bin/htmldiff ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'htmldiff' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", __FILE__)
10
+
11
+ require 'rubygems'
12
+ require 'bundler/setup'
13
+
14
+ load Gem.bin_path('diff-lcs', 'htmldiff')
data/bin/ldiff ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'ldiff' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", __FILE__)
10
+
11
+ require 'rubygems'
12
+ require 'bundler/setup'
13
+
14
+ load Gem.bin_path('diff-lcs', 'ldiff')
data/bin/rake ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rake' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", __FILE__)
10
+
11
+ require 'rubygems'
12
+ require 'bundler/setup'
13
+
14
+ load Gem.bin_path('rake', 'rake')
data/bin/rspec ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rspec' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", __FILE__)
10
+
11
+ require 'rubygems'
12
+ require 'bundler/setup'
13
+
14
+ load Gem.bin_path('rspec-core', 'rspec')
data/bin/tt ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'tt' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", __FILE__)
10
+
11
+ require 'rubygems'
12
+ require 'bundler/setup'
13
+
14
+ load Gem.bin_path('treetop', 'tt')
data/bin/unit_diff ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'unit_diff' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", __FILE__)
10
+
11
+ require 'rubygems'
12
+ require 'bundler/setup'
13
+
14
+ load Gem.bin_path('autotest', 'unit_diff')
@@ -3,27 +3,13 @@
3
3
  module FastMailer
4
4
  class Configuration
5
5
 
6
- TEST_CONFIGURATION = {
7
- :something => :useful
8
- }
9
-
10
- def self.enable_testing!
11
- def self.smtp_configuration(options = nil)
12
- TEST_CONFIGURATION
6
+ def self.smtp_configuration(options = nil)
7
+ if options.is_a? Hash
8
+ options
9
+ else
10
+ eval(File.read(options || File.expand_path("~/.config/smtp.rb")))
13
11
  end
14
12
  end
15
13
 
16
- def self.disable_testing!
17
- def self.smtp_configuration(options = nil)
18
- if options.is_a? Hash
19
- options
20
- else
21
- eval(File.read(options || File.expand_path("~/.config/smtp.rb")))
22
- end
23
- end
24
- end
25
-
26
- disable_testing!
27
-
28
14
  end
29
15
  end
@@ -0,0 +1,62 @@
1
+ module FastMailer
2
+ class Mailer
3
+
4
+ def initialize(options = nil)
5
+ @options = options
6
+ end
7
+
8
+ def send_all(mail_generator)
9
+ @mail_generator = mail_generator
10
+ @mutex = Mutex.new
11
+
12
+ tcount = (@options && @options[:max_connections]) || 1
13
+ threads = []
14
+
15
+ if tcount > 1
16
+ tcount.times do |n|
17
+ threads << Thread.new(n) do |tid|
18
+ send_until_done
19
+ end
20
+ end
21
+
22
+ threads.each { |thr| thr.join }
23
+ else
24
+ send_until_done
25
+ end
26
+ end
27
+
28
+
29
+ private
30
+ def send_until_done
31
+ smtp = FastMailer::SMTP.new @options
32
+ while (true)
33
+ begin
34
+ peek_mail
35
+ smtp.open do
36
+ while true
37
+ smtp.deliver next_mail
38
+ end
39
+ end
40
+ rescue StandardError => e
41
+ raise e if StopIteration === e
42
+ sleep 2 unless FastMailer.test_mode
43
+ end
44
+ end
45
+ rescue StopIteration
46
+ # Expected.
47
+ end
48
+
49
+ def next_mail
50
+ @mutex.synchronize do
51
+ @mail_generator.next
52
+ end
53
+ end
54
+
55
+ def peek_mail
56
+ @mutex.synchronize do
57
+ @mail_generator.peek
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,44 @@
1
+
2
+ module FastMailer
3
+ # Original mockup from ActionMailer
4
+ class MockSMTP
5
+
6
+ def self.deliveries
7
+ @@deliveries
8
+ end
9
+
10
+ def initialize(*args)
11
+ @@deliveries ||= []
12
+ end
13
+
14
+ def sendmail(mail, from, to)
15
+ @@deliveries << [mail, from, to]
16
+ end
17
+
18
+ def start(*args)
19
+ yield self
20
+ end
21
+
22
+ def self.clear_deliveries
23
+ @@deliveries = []
24
+ end
25
+
26
+ # in the standard lib: net/smtp.rb line 577
27
+ # a TypeError is thrown unless this arg is a
28
+ # kind of OpenSSL::SSL::SSLContext
29
+ def enable_tls(context = nil)
30
+ if context && context.kind_of?(OpenSSL::SSL::SSLContext)
31
+ true
32
+ elsif context
33
+ raise TypeError,
34
+ "wrong argument (#{context.class})! "+
35
+ "(Expected kind of OpenSSL::SSL::SSLContext)"
36
+ end
37
+ end
38
+
39
+ def enable_starttls_auto
40
+ true
41
+ end
42
+
43
+ end
44
+ end
@@ -13,6 +13,11 @@ module FastMailer
13
13
  # sending mail on the same connection.
14
14
  class SMTP
15
15
 
16
+ include Hooks
17
+
18
+ define_hook :before_deliver
19
+ define_hook :after_deliver
20
+
16
21
  attr_accessor :configuration
17
22
 
18
23
  def initialize(options = nil)
@@ -25,7 +30,7 @@ module FastMailer
25
30
  configuration[:host] ||= configuration[:address]
26
31
  configuration[:username] ||= configuration[:user_name]
27
32
 
28
- @smtp = Net::SMTP.new(configuration[:host], configuration[:port])
33
+ @smtp = connection_class.new(configuration[:host], configuration[:port])
29
34
  if configuration[:enable_starttls_auto]
30
35
  smtp.enable_starttls_auto if smtp.respond_to?(:enable_starttls_auto)
31
36
  end
@@ -49,30 +54,45 @@ module FastMailer
49
54
  end
50
55
 
51
56
  private
57
+ def connection_class
58
+ FastMailer.test_mode ? FastMailer::MockSMTP : Net::SMTP
59
+ end
60
+
61
+ def skip_delivery!
62
+ @skip_delivery = true
63
+ end
64
+
52
65
  def perform_delivery(mail)
66
+ run_hook :before_deliver, mail
53
67
 
54
- # Set the envelope from to be either the return-path, the sender or the first from address
55
- envelope_from = mail.return_path || mail.sender || mail.from_addrs.first
56
- if envelope_from.blank?
57
- raise ArgumentError.new('A sender (Return-Path, Sender or From) required to send a message')
58
- end
68
+ if !@skip_delivery
69
+ # Set the envelope from to be either the return-path, the sender or the first from address
70
+ envelope_from = mail.return_path || mail.sender || mail.from_addrs.first
71
+ if envelope_from.blank?
72
+ raise ArgumentError.new('A sender (Return-Path, Sender or From) required to send a message')
73
+ end
59
74
 
60
- destinations ||= mail.destinations if mail.respond_to?(:destinations) && mail.destinations
61
- if destinations.blank?
62
- raise ArgumentError.new('At least one recipient (To, Cc or Bcc) is required to send a message')
63
- end
75
+ destinations ||= mail.destinations if mail.respond_to?(:destinations) && mail.destinations
76
+ if destinations.blank?
77
+ raise ArgumentError.new('At least one recipient (To, Cc or Bcc) is required to send a message')
78
+ end
64
79
 
65
- message ||= mail.encoded if mail.respond_to?(:encoded)
66
- if message.blank?
67
- raise ArgumentError.new('A encoded content is required to send a message')
68
- end
80
+ message ||= mail.encoded if mail.respond_to?(:encoded)
81
+ if message.blank?
82
+ raise ArgumentError.new('A encoded content is required to send a message')
83
+ end
69
84
 
70
- begin
71
- @smtp.sendmail(message, envelope_from, destinations)
72
- rescue e
73
- @smtp = nil
74
- raise e
85
+ begin
86
+ @smtp.sendmail(message, envelope_from, destinations)
87
+ run_hook :after_deliver, mail
88
+ rescue Exception => e
89
+ @smtp = nil
90
+ run_hook :after_deliver, mail, e
91
+ raise e
92
+ end
75
93
  end
94
+ ensure
95
+ @skip_delivery = false
76
96
  end
77
97
 
78
98
  end
data/lib/fast-mailer.rb CHANGED
@@ -1,5 +1,22 @@
1
1
 
2
2
  require 'mail'
3
+ require 'hooks'
3
4
 
4
5
  require 'fast-mailer/configuration'
5
6
  require 'fast-mailer/smtp'
7
+ require 'fast-mailer/mailer'
8
+
9
+ module FastMailer
10
+
11
+ class <<self
12
+ def test_mode=(value)
13
+ require 'fast-mailer/mock_smtp' if value
14
+ @@test_mode = value
15
+ end
16
+
17
+ def test_mode
18
+ @@test_mode ||= false
19
+ end
20
+ end
21
+
22
+ end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 0
8
7
  - 1
9
- version: 0.0.1
8
+ - 0
9
+ version: 0.1.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Erik Hansson
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-09-29 00:00:00 +02:00
17
+ date: 2010-10-01 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -46,9 +46,23 @@ dependencies:
46
46
  type: :runtime
47
47
  version_requirements: *id002
48
48
  - !ruby/object:Gem::Dependency
49
- name: bundler
49
+ name: hooks
50
50
  prerelease: false
51
51
  requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 0
58
+ - 1
59
+ version: "0.1"
60
+ type: :runtime
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: bundler
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
52
66
  none: false
53
67
  requirements:
54
68
  - - ~>
@@ -59,11 +73,11 @@ dependencies:
59
73
  - 0
60
74
  version: 1.0.0
61
75
  type: :development
62
- version_requirements: *id003
76
+ version_requirements: *id004
63
77
  - !ruby/object:Gem::Dependency
64
78
  name: rspec
65
79
  prerelease: false
66
- requirement: &id004 !ruby/object:Gem::Requirement
80
+ requirement: &id005 !ruby/object:Gem::Requirement
67
81
  none: false
68
82
  requirements:
69
83
  - - ~>
@@ -76,11 +90,11 @@ dependencies:
76
90
  - 22
77
91
  version: 2.0.0.beta.22
78
92
  type: :development
79
- version_requirements: *id004
93
+ version_requirements: *id005
80
94
  - !ruby/object:Gem::Dependency
81
95
  name: rake
82
96
  prerelease: false
83
- requirement: &id005 !ruby/object:Gem::Requirement
97
+ requirement: &id006 !ruby/object:Gem::Requirement
84
98
  none: false
85
99
  requirements:
86
100
  - - ~>
@@ -91,11 +105,11 @@ dependencies:
91
105
  - 7
92
106
  version: 0.8.7
93
107
  type: :development
94
- version_requirements: *id005
108
+ version_requirements: *id006
95
109
  - !ruby/object:Gem::Dependency
96
110
  name: autotest
97
111
  prerelease: false
98
- requirement: &id006 !ruby/object:Gem::Requirement
112
+ requirement: &id007 !ruby/object:Gem::Requirement
99
113
  none: false
100
114
  requirements:
101
115
  - - ">="
@@ -104,7 +118,7 @@ dependencies:
104
118
  - 0
105
119
  version: "0"
106
120
  type: :development
107
- version_requirements: *id006
121
+ version_requirements: *id007
108
122
  description: Helps with sending emails fast, and with convenient configuration.
109
123
  email:
110
124
  - erik@bits2life.com
@@ -115,7 +129,16 @@ extensions: []
115
129
  extra_rdoc_files: []
116
130
 
117
131
  files:
132
+ - bin/autotest
133
+ - bin/htmldiff
134
+ - bin/ldiff
135
+ - bin/rake
136
+ - bin/rspec
137
+ - bin/tt
138
+ - bin/unit_diff
118
139
  - lib/fast-mailer/configuration.rb
140
+ - lib/fast-mailer/mailer.rb
141
+ - lib/fast-mailer/mock_smtp.rb
119
142
  - lib/fast-mailer/smtp.rb
120
143
  - lib/fast-mailer.rb
121
144
  - LICENCE