fast-mailer 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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