malone-acd 1.0.7

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d8304a6c962c3ce511c5c6013fc12e79f089fecf
4
+ data.tar.gz: dc8d668a2610da9dc24617f906431e6b83191e75
5
+ SHA512:
6
+ metadata.gz: 2c10db3e69a24e740e71ff7025c573d0f2d17f24e82eca81420fec1ddf0af2d9d2ffe781c4b0c5cbc8193ed796a2810f3e8135fc8efb4abe02c4616be78d061b
7
+ data.tar.gz: cbfe96fe372643cc263d0e11af4e64febdf936077ac889760edd5195ab01d0620acbc9d31ffee11ddcc6a214b904120a8548e266d8832199cd36aae1a834ae7a
data/CHANGELOG ADDED
@@ -0,0 +1,21 @@
1
+ 1.0.0
2
+
3
+ - Malone.configure has been replaced with Malone.connect
4
+ Use Malone.current to retrieve the last configured Malone
5
+ instance (using Malone.connect)
6
+
7
+ - Malone.deliver has been replaced with an instance method.
8
+ Call deliver (with the same arguments as before) on the
9
+ return value of Malone.connect or Malone.current.
10
+
11
+ - Malone#deliver now receives :text and :html instead of :body.
12
+
13
+ - No need to pass in TLS. it's tries to do TLS automatically.
14
+
15
+ - Errors during SMTP authentication (and any other error) aren't
16
+ trapped silently now. (via @tizoc, @elpollila)
17
+
18
+ - Configuration parameters are more strict (i.e. passing :password
19
+ would throw a NoMethodError via @tizoc, @elpollila)
20
+
21
+ - malone/sandbox has been renamed to malone/test.
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010 Cyril David
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,82 @@
1
+ malone(1) -- send mail using smtp without any fuss
2
+ ==================================================
3
+
4
+ ## USAGE
5
+
6
+ require "malone"
7
+
8
+ # Typically you would do this somewhere in the bootstrapping
9
+ # part of your application
10
+
11
+ m = Malone.connect(url: "smtp://foo%40bar.com:pass@smtp.gmail.com:587",
12
+ domain: "mysite.com")
13
+
14
+ m.deliver(from: "me@me.com", to: "you@me.com",
15
+ subject: "Test subject", text: "Great!")
16
+
17
+ # Malone.current will now remember the last configuration you setup.
18
+ Malone.current.config == m.config
19
+
20
+ # Now you can also do Malone.deliver, which is syntactic sugar
21
+ # for Malone.current.deliver
22
+ Malone.deliver(from: "me@me.com", to: "you@me.com",
23
+ subject: "Test subject", text: "Great!")
24
+
25
+ # Also starting with Malone 1.0, you can pass in :html
26
+ # for multipart emails.
27
+
28
+ Malone.deliver(from: "me@me.com", to: "you@me.com",
29
+ subject: "Test subject",
30
+ text: "Great!", html: "<b>Great!</b>")
31
+
32
+
33
+ ## TESTING
34
+
35
+ require "malone/test"
36
+
37
+ m = Malone.connect(url: "smtp://foo%40bar.com:pass@smtp.gmail.com:587",
38
+ domain: "mysite.com")
39
+
40
+ m.deliver(from: "me@me.com", to: "you@me.com",
41
+ subject: "Test subject", text: "Great!")
42
+
43
+ Malone.deliveries.size == 1
44
+ # => true
45
+
46
+ mail = Malone.deliveries.first
47
+
48
+ "me@me.com" == mail.from
49
+ # => true
50
+
51
+ "you@me.com" == mail.to
52
+ # => true
53
+
54
+ "FooBar" == mail.text
55
+ # => true
56
+
57
+ "Hello World" == envelope.subject
58
+ # => true
59
+
60
+ ## INSTALLATION
61
+
62
+ gem install malone
63
+
64
+ ## CONFIGURATION TIPS
65
+
66
+ If you're used to doing configuration via environment
67
+ variables, similar to how Heroku does configuration, then
68
+ you can simply set an environment variable in your
69
+ production machine like so:
70
+
71
+ export MALONE_URL=smtp://foo%40bar.com:pass@smtp.gmail.com:587
72
+
73
+ Then you can connect using the environment variable in your
74
+ code like so:
75
+
76
+ Malone.connect(url: ENV["MALONE_URL"])
77
+
78
+ # or quite simply
79
+ Malone.connect
80
+
81
+ By default Malone tries for the environment variable `MALONE_URL` when
82
+ you call `Malone.connect` without any arguments.
@@ -0,0 +1,13 @@
1
+ require "ostruct"
2
+
3
+ class Malone
4
+ def self.deliveries
5
+ @deliveries ||= []
6
+ end
7
+
8
+ def deliver(*args)
9
+ self.class.deliveries << OpenStruct.new(*args)
10
+ end
11
+ end
12
+
13
+
data/lib/malone.rb ADDED
@@ -0,0 +1,127 @@
1
+ require "cgi"
2
+ require "mailfactory"
3
+ require "net/smtp"
4
+ require "uri"
5
+
6
+ class Malone
7
+ attr :config
8
+
9
+ def self.connect(options = {})
10
+ @config = Configuration.new(options)
11
+
12
+ current
13
+ end
14
+
15
+ def self.current
16
+ unless defined?(@config)
17
+ raise RuntimeError, "Missing configuration: Try doing `Malone.connect`."
18
+ end
19
+
20
+ return new(@config)
21
+ end
22
+
23
+ def self.deliver(dict)
24
+ current.deliver(dict)
25
+ end
26
+
27
+ def initialize(config)
28
+ @config = config
29
+ end
30
+
31
+ def deliver(dict)
32
+ mail = envelope(dict)
33
+
34
+ smtp = Net::SMTP.new(config.host, config.port)
35
+ smtp.enable_starttls_auto if config.tls
36
+
37
+ begin
38
+ smtp.start(config.domain, config.user, config.password, config.auth)
39
+ smtp.send_message(mail.to_s, mail.from.first, *recipients(mail))
40
+ ensure
41
+ smtp.finish if smtp.started?
42
+ end
43
+ end
44
+
45
+ def recipients(mail)
46
+ [].tap do |ret|
47
+ ret.push(*mail.to)
48
+ ret.push(*mail.cc)
49
+ ret.push(*mail.bcc)
50
+ end
51
+ end
52
+
53
+ def envelope(dict)
54
+ envelope = Envelope.new
55
+ envelope.from = dict[:from]
56
+ envelope.to = dict[:to]
57
+ envelope.replyto = dict[:replyto]
58
+ envelope.cc = dict[:cc] if dict[:cc]
59
+ envelope.bcc = dict[:bcc] if dict[:bcc]
60
+ envelope.text = dict[:text]
61
+ envelope.rawhtml = dict[:html] if dict[:html]
62
+ envelope.subject = dict[:subject]
63
+
64
+ envelope.attach(dict[:attach]) if dict[:attach]
65
+
66
+ envelope.add_attachment_as(*dict[:attach_as]) if dict[:attach_as]
67
+
68
+ return envelope
69
+ end
70
+
71
+ class Configuration
72
+ attr_accessor :host
73
+ attr_accessor :port
74
+ attr_accessor :user
75
+ attr_accessor :password
76
+ attr_accessor :domain
77
+ attr_accessor :auth
78
+ attr_accessor :tls
79
+
80
+ def initialize(options)
81
+ opts = options.dup
82
+
83
+ @tls = true
84
+
85
+ url = opts.delete(:url) || ENV["MALONE_URL"]
86
+
87
+ if url
88
+ uri = URI(url)
89
+
90
+ opts[:host] ||= uri.host
91
+ opts[:port] ||= uri.port.to_i
92
+ opts[:user] ||= unescaped(uri.user)
93
+ opts[:password] ||= unescaped(uri.password)
94
+ end
95
+
96
+ opts.each do |key, val|
97
+ send(:"#{key}=", val)
98
+ end
99
+ end
100
+
101
+ def auth=(val)
102
+ @auth = val
103
+ @auth = @auth.to_sym if @auth
104
+ end
105
+
106
+ private
107
+ def unescaped(val)
108
+ return if val.to_s.empty?
109
+
110
+ CGI.unescape(val)
111
+ end
112
+ end
113
+
114
+ class Envelope < MailFactory
115
+ attr :bcc
116
+
117
+ def initialize
118
+ super
119
+
120
+ @bcc = []
121
+ end
122
+
123
+ def bcc=(bcc)
124
+ @bcc.push(bcc)
125
+ end
126
+ end
127
+ end
data/malone.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'malone-acd'
3
+ s.version = "1.0.7"
4
+ s.summary = %{Dead-simple Ruby mailing solution which always delivers.}
5
+ s.date = "2011-01-10"
6
+ s.author = "Cyril David"
7
+ s.email = "me@cyrildavid.com"
8
+ s.homepage = "http://github.com/cyx/malone"
9
+
10
+ s.files = Dir[
11
+ "CHANGELOG",
12
+ "LICENSE",
13
+ "README.md",
14
+ "lib/**/*.rb",
15
+ "test/*.*",
16
+ "*.gemspec"
17
+ ]
18
+
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_dependency "mailfactory-acd"
22
+ s.add_development_dependency "cutest-cj"
23
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,4 @@
1
+ $:.unshift(File.expand_path("../lib", File.dirname(__FILE__)))
2
+
3
+ require "cutest"
4
+ require "malone"
data/test/malone.rb ADDED
@@ -0,0 +1,223 @@
1
+ require_relative "helper"
2
+
3
+ test "basic configuration" do
4
+ m = Malone.connect(host: "smtp.gmail.com", port: 587,
5
+ user: "foo@bar.com", password: "pass1234",
6
+ domain: "foo.com", auth: "login")
7
+
8
+ c = m.config
9
+
10
+ assert_equal "smtp.gmail.com", c.host
11
+ assert_equal 587, c.port
12
+ assert_equal "foo@bar.com", c.user
13
+ assert_equal "pass1234", c.password
14
+ assert_equal "foo.com", c.domain
15
+ assert_equal :login, c.auth
16
+ end
17
+
18
+ test "configuration via url" do
19
+ m = Malone.connect(url: "smtp://foo%40bar.com:pass1234@smtp.gmail.com:587")
20
+
21
+ c = m.config
22
+
23
+ assert_equal "smtp.gmail.com", c.host
24
+ assert_equal 587, c.port
25
+ assert_equal "foo@bar.com", c.user
26
+ assert_equal "pass1234", c.password
27
+ end
28
+
29
+ test "configuration via url and params" do
30
+ m = Malone.connect(url: "smtp://foo%40bar.com:pass1234@smtp.gmail.com:587",
31
+ domain: "foo.com", auth: "login", password: "barbaz123")
32
+
33
+ c = m.config
34
+
35
+ assert_equal "smtp.gmail.com", c.host
36
+ assert_equal 587, c.port
37
+ assert_equal "foo@bar.com", c.user
38
+ assert_equal "foo.com", c.domain
39
+ assert_equal :login, c.auth
40
+ assert_equal true, c.tls
41
+
42
+ # We verify that parameters passed takes precedence over the URL.
43
+ assert_equal "barbaz123", c.password
44
+ end
45
+
46
+ test "configuration via MALONE_URL" do
47
+ ENV["MALONE_URL"] = "smtp://foo%40bar.com:pass1234@smtp.gmail.com:587"
48
+
49
+ m = Malone.connect(domain: "foo.com", auth: "login", tls: false)
50
+ c = m.config
51
+
52
+ assert_equal "smtp.gmail.com", c.host
53
+ assert_equal 587, c.port
54
+ assert_equal "foo@bar.com", c.user
55
+ assert_equal "foo.com", c.domain
56
+ assert_equal :login, c.auth
57
+ assert_equal false, c.tls
58
+ end
59
+
60
+ test "typos in configuration" do
61
+ assert_raise NoMethodError do
62
+ Malone.connect(pass: "pass")
63
+ end
64
+ end
65
+
66
+ test "Malone.connect doesn't mutate the options" do
67
+ ex = nil
68
+ begin
69
+ Malone.connect({}.freeze)
70
+ rescue RuntimeError => ex
71
+ end
72
+
73
+ assert_equal nil, ex
74
+ end
75
+
76
+ test "Malone.current" do
77
+ Malone.connect(url: "smtp://foo%40bar.com:pass1234@smtp.gmail.com:587")
78
+
79
+ c = Malone.current.config
80
+
81
+ assert_equal "smtp.gmail.com", c.host
82
+ assert_equal 587, c.port
83
+ assert_equal "foo@bar.com", c.user
84
+ assert_equal "pass1234", c.password
85
+ end
86
+
87
+ test "#envelope" do
88
+ m = Malone.connect
89
+
90
+ mail = m.envelope(to: "recipient@me.com", from: "no-reply@mydomain.com",
91
+ subject: "SUB", text: "TEXT", html: "<h1>TEXT</h1>",
92
+ cc: "cc@me.com", bcc: "bcc@me.com",
93
+ replyto: "other@me.com")
94
+
95
+ assert_equal ["recipient@me.com"], mail.to
96
+ assert_equal ["cc@me.com"], mail.cc
97
+ assert_equal ["bcc@me.com"], mail.bcc
98
+ assert_equal ["no-reply@mydomain.com"], mail.from
99
+ assert_equal ["=?utf-8?Q?SUB?="], mail.subject
100
+ assert_equal "other@me.com", mail.replyto
101
+
102
+ assert_equal "TEXT", mail.instance_variable_get(:@text)
103
+ assert_equal "<h1>TEXT</h1>", mail.instance_variable_get(:@html)
104
+ end
105
+
106
+ scope do
107
+ class FakeSMTP < Struct.new(:host, :port)
108
+ def enable_starttls_auto
109
+ @enable_starttls_auto = true
110
+ end
111
+
112
+ def start(domain, user, password, auth)
113
+ @domain, @user, @password, @auth = domain, user, password, auth
114
+
115
+ @started = true
116
+ end
117
+
118
+ def started?
119
+ defined?(@started)
120
+ end
121
+
122
+ def finish
123
+ @finish = true
124
+ end
125
+
126
+ def send_message(blob, from, *recipients)
127
+ @blob, @from, @recipients = blob, from, recipients
128
+ end
129
+
130
+ def [](key)
131
+ instance_variable_get(:"@#{key}")
132
+ end
133
+ end
134
+
135
+ module Net
136
+ def SMTP.new(host, port)
137
+ $smtp = FakeSMTP.new(host, port)
138
+ end
139
+ end
140
+
141
+ setup do
142
+ Malone.connect(url: "smtp://foo%40bar.com:pass1234@smtp.gmail.com:587",
143
+ domain: "mydomain.com", auth: :login)
144
+ end
145
+
146
+ test "delivering successfully" do |m|
147
+ m.deliver(to: "recipient@me.com", from: "no-reply@mydomain.com",
148
+ subject: "SUB", text: "TEXT", cc: "cc@me.com", bcc: "bcc@me.com")
149
+
150
+ assert_equal "smtp.gmail.com", $smtp.host
151
+ assert_equal 587, $smtp.port
152
+
153
+ assert $smtp[:enable_starttls_auto]
154
+ assert_equal "mydomain.com", $smtp[:domain]
155
+ assert_equal "foo@bar.com", $smtp[:user]
156
+ assert_equal "pass1234", $smtp[:password]
157
+ assert_equal :login, $smtp[:auth]
158
+
159
+
160
+ assert_equal ["recipient@me.com", "cc@me.com", "bcc@me.com"], $smtp[:recipients]
161
+ assert_equal "no-reply@mydomain.com", $smtp[:from]
162
+
163
+ assert ! $smtp[:blob].include?("bcc@me.com")
164
+
165
+ assert $smtp[:started]
166
+ assert $smtp[:finish]
167
+ end
168
+
169
+ test "Malone.deliver forwards to Malone.current" do |m|
170
+ Malone.deliver(to: "recipient@me.com", from: "no-reply@mydomain.com",
171
+ subject: "SUB", text: "TEXT")
172
+
173
+ assert_equal "smtp.gmail.com", $smtp.host
174
+ assert_equal 587, $smtp.port
175
+
176
+ assert $smtp[:enable_starttls_auto]
177
+ assert_equal "mydomain.com", $smtp[:domain]
178
+ assert_equal "foo@bar.com", $smtp[:user]
179
+ assert_equal "pass1234", $smtp[:password]
180
+ assert_equal :login, $smtp[:auth]
181
+
182
+ assert_equal ["recipient@me.com"], $smtp[:recipients]
183
+ assert_equal "no-reply@mydomain.com", $smtp[:from]
184
+
185
+ assert $smtp[:started]
186
+ assert $smtp[:finish]
187
+ end
188
+
189
+ test "calls #finish even when it fails during send_message" do |m|
190
+ class FakeSMTP
191
+ def send_message(*args)
192
+ raise
193
+ end
194
+ end
195
+
196
+ begin
197
+ m.deliver(to: "recipient@me.com", from: "no-reply@mydomain.com",
198
+ subject: "SUB", text: "TEXT")
199
+ rescue
200
+ end
201
+
202
+ assert $smtp[:started]
203
+ assert $smtp[:finish]
204
+ end
205
+ end
206
+
207
+ test "sandbox" do
208
+ require "malone/test"
209
+
210
+ m = Malone.connect
211
+ m.deliver(to: "recipient@me.com", from: "no-reply@mydomain.com",
212
+ subject: "SUB", text: "TEXT", html: "<h1>TEXT</h1>")
213
+
214
+ assert_equal 1, Malone.deliveries.size
215
+
216
+ mail = Malone.deliveries.first
217
+
218
+ assert_equal "no-reply@mydomain.com", mail.from
219
+ assert_equal "recipient@me.com", mail.to
220
+ assert_equal "SUB", mail.subject
221
+ assert_equal "TEXT", mail.text
222
+ assert_equal "<h1>TEXT</h1>", mail.html
223
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: malone-acd
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.7
5
+ platform: ruby
6
+ authors:
7
+ - Cyril David
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2011-01-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mailfactory-acd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: cutest-cj
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description:
42
+ email: me@cyrildavid.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - CHANGELOG
48
+ - LICENSE
49
+ - README.md
50
+ - lib/malone.rb
51
+ - lib/malone/test.rb
52
+ - malone.gemspec
53
+ - test/helper.rb
54
+ - test/malone.rb
55
+ homepage: http://github.com/cyx/malone
56
+ licenses: []
57
+ metadata: {}
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ requirements: []
73
+ rubyforge_project:
74
+ rubygems_version: 2.2.2
75
+ signing_key:
76
+ specification_version: 4
77
+ summary: Dead-simple Ruby mailing solution which always delivers.
78
+ test_files: []