mailgun 0.7 → 0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -4
- data/CONTRIBUTORS.md +23 -0
- data/README.md +31 -16
- data/lib/mailgun.rb +4 -1
- data/lib/mailgun/base.rb +4 -4
- data/lib/mailgun/bounce.rb +24 -3
- data/lib/mailgun/message.rb +1 -1
- data/lib/multimap/.gitignore +4 -0
- data/lib/multimap/LICENSE +20 -0
- data/lib/multimap/README.rdoc +16 -0
- data/lib/multimap/Rakefile +34 -0
- data/lib/multimap/benchmarks/bm_nested_multimap_construction.rb +60 -0
- data/lib/multimap/benchmarks/bm_nested_multimap_lookup.rb +33 -0
- data/lib/multimap/ext/extconf.rb +6 -0
- data/lib/multimap/ext/nested_multimap_ext.c +24 -0
- data/lib/multimap/extras/graphing.rb +83 -0
- data/lib/multimap/lib/multimap.rb +569 -0
- data/lib/multimap/lib/multiset.rb +185 -0
- data/lib/multimap/lib/nested_multimap.rb +158 -0
- data/lib/multimap/spec/enumerable_examples.rb +50 -0
- data/lib/multimap/spec/hash_examples.rb +264 -0
- data/lib/multimap/spec/multimap_spec.rb +45 -0
- data/lib/multimap/spec/multiset_spec.rb +184 -0
- data/lib/multimap/spec/nested_multimap_spec.rb +202 -0
- data/lib/multimap/spec/set_examples.rb +301 -0
- data/lib/multimap/spec/spec_helper.rb +67 -0
- data/mailgun.gemspec +4 -4
- data/spec/base_spec.rb +2 -2
- data/spec/bounce_spec.rb +12 -0
- metadata +43 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20809378b057a083d20b98dd3dffb1d771d2845e
|
4
|
+
data.tar.gz: b063e69d0b35dca7f8a934e7a2e2fd3f9f5d57ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a568bf6b8ca38bd594d0f08e336c2d3a93961b32fe216e2d954e80b527675d8f8cbd91de0c8413e540135abed41be64e329e6dfe81911d71ad14196027daeed9
|
7
|
+
data.tar.gz: b307a01536f51da5b8bbd462ae477105685e95adab6e48f8c6c02dca6438f2affb929e8a0e76da4830dcee00fb33d9cbd4c40bdfad51b4b264bad3ecf128492e
|
data/.gitignore
CHANGED
data/CONTRIBUTORS.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
* Alan deLevie / ([@adelevie](http://github.com/adelevie))
|
2
|
+
* Sending email
|
3
|
+
|
4
|
+
* Andrés Bravo / ([@andresbravog](http://github.com/andresbravog))
|
5
|
+
* Support for bounces API
|
6
|
+
|
7
|
+
* [@gabriel](http://github.com/gabriel)
|
8
|
+
* Fix to accept domain in options
|
9
|
+
|
10
|
+
* Kaz Walker / [@KazW](http://github.com/KazW>)
|
11
|
+
* Syntax highlighting for readme
|
12
|
+
|
13
|
+
* [@mirzac](http://github.com/mirzac>)
|
14
|
+
* Fix to accept domain in options
|
15
|
+
|
16
|
+
* [@kdayton-](http://github.com/kdayton->)
|
17
|
+
* Support for domains API
|
18
|
+
|
19
|
+
* Scott Carleton / [@scotterc](http://github.com/scotterc)
|
20
|
+
* new functionality and improvements
|
21
|
+
|
22
|
+
* Yomi Colledge / [@baphled](http://github.com/baphled)
|
23
|
+
* For refactoring API configuration and some documentation
|
data/README.md
CHANGED
@@ -17,14 +17,14 @@ Mailgun exposes the following resources:
|
|
17
17
|
* Complaints
|
18
18
|
* Domain management
|
19
19
|
|
20
|
-
Patches are welcome (and easy!).
|
20
|
+
Patches are welcome (and easy!).
|
21
21
|
|
22
22
|
## Sending mail using ActionMailer
|
23
23
|
|
24
24
|
If you simply want to send mail using Mailgun, just set the smtp settings in the Rails application like the following. Replace wherever necessary in the following snippet :)
|
25
25
|
```ruby
|
26
26
|
ActionMailer::Base.smtp_settings = {
|
27
|
-
:port => 587,
|
27
|
+
:port => 587,
|
28
28
|
:address => 'smtp.mailgun.org',
|
29
29
|
:user_name => 'postmaster@your.mailgun.domain',
|
30
30
|
:password => 'mailgun-smtp-password',
|
@@ -71,7 +71,7 @@ parameters = {
|
|
71
71
|
@mailgun.lists.create "devs@your.mailgun.domain"
|
72
72
|
|
73
73
|
# List all Mailing lists
|
74
|
-
@mailgun.lists.
|
74
|
+
@mailgun.lists.list
|
75
75
|
|
76
76
|
# Find a mailing list
|
77
77
|
@mailgun.lists.find "devs@your.mailgun.domain"
|
@@ -114,6 +114,21 @@ parameters = {
|
|
114
114
|
@mailbox.mailboxes.destroy "bond@mi6.co.uk"
|
115
115
|
```
|
116
116
|
|
117
|
+
#### Bounces
|
118
|
+
```ruby
|
119
|
+
# List last bounces (100 limit)
|
120
|
+
@mailgun.bounces.list
|
121
|
+
|
122
|
+
# Find bounces
|
123
|
+
@mailgun.bounces.find "user@ema.il"
|
124
|
+
|
125
|
+
# Add bounce
|
126
|
+
@maligun.bounces.add "user@ema.il"
|
127
|
+
|
128
|
+
# Clean user bounces
|
129
|
+
@mailbox.bounces.destroy "user@ema.il"
|
130
|
+
```
|
131
|
+
|
117
132
|
#### Routes
|
118
133
|
```ruby
|
119
134
|
# Initialize your Mailgun object:
|
@@ -137,9 +152,9 @@ parameters = {
|
|
137
152
|
# Update a route via its id
|
138
153
|
# (all keys are optional)
|
139
154
|
@mailgun.routes.update "4e97c1b2ba8a48567f007fb6", {
|
140
|
-
:priority
|
141
|
-
:
|
142
|
-
:actions
|
155
|
+
:priority => 2,
|
156
|
+
:expression => [:match_header, :subject, "*.support"],
|
157
|
+
:actions => [[:forward, "http://new-site.com/incoming-emails"]]
|
143
158
|
}
|
144
159
|
|
145
160
|
# Destroy a route via its id
|
@@ -181,9 +196,10 @@ Supported route actions are: `:forward`, and `:stop`
|
|
181
196
|
* Submit your change as a Pull Request and update the GitHub issue to let us know it is ready for review.
|
182
197
|
|
183
198
|
|
199
|
+
|
200
|
+
|
184
201
|
## TODO
|
185
202
|
|
186
|
-
* Mailgun() is overwriting api key. api key is not persisting
|
187
203
|
* Add skip and limit functionality
|
188
204
|
* Distinguish failed in logs
|
189
205
|
* Distinguish delivered in logs
|
@@ -192,18 +208,17 @@ Supported route actions are: `:forward`, and `:stop`
|
|
192
208
|
* Campaign?
|
193
209
|
|
194
210
|
|
195
|
-
##
|
211
|
+
## Maintainer
|
196
212
|
|
197
|
-
|
198
|
-
|
213
|
+
Akash Manohar / [@HashNuke](http://github.com/HashNuke)
|
214
|
+
|
215
|
+
|
216
|
+
## Authors
|
199
217
|
|
200
|
-
|
218
|
+
* Akash Manohar / [@HashNuke](http://github.com/HashNuke)
|
219
|
+
* Sean Grove / [@sgrove](http://github.com/sgrove)
|
201
220
|
|
202
|
-
|
203
|
-
* Scott Carleton ([@scotterc](http://github.com/scotterc)) - new functionality and improvements
|
204
|
-
* Alan deLevie ([@adelevie](http://github.com/adelevie)) - Sending email
|
205
|
-
* kdayton (<http://github.com/kdayton->) - Support for domains API
|
206
|
-
* gabriel (<http://github.com/gabriel>) - Fix to accept domain in options
|
221
|
+
See CONTRIBUTORS.md file for contributor credits.
|
207
222
|
|
208
223
|
## License
|
209
224
|
|
data/lib/mailgun.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require "rest-client"
|
2
2
|
require "json"
|
3
|
-
require "multimap"
|
3
|
+
require "multimap/lib/multimap"
|
4
|
+
require "multimap/lib/multiset"
|
5
|
+
require "multimap/lib/nested_multimap"
|
4
6
|
|
5
7
|
require "mailgun/mailgun_error"
|
6
8
|
require "mailgun/base"
|
@@ -19,5 +21,6 @@ require "mailgun/message"
|
|
19
21
|
|
20
22
|
def Mailgun(options={})
|
21
23
|
options[:api_key] = Mailgun.api_key if Mailgun.api_key
|
24
|
+
options[:domain] = Mailgun.domain if Mailgun.domain
|
22
25
|
Mailgun::Base.new(options)
|
23
26
|
end
|
data/lib/mailgun/base.rb
CHANGED
@@ -13,7 +13,7 @@ module Mailgun
|
|
13
13
|
Mailgun.api_version = options.fetch(:api_version) { "v2" }
|
14
14
|
Mailgun.test_mode = options.fetch(:test_mode) { false }
|
15
15
|
Mailgun.api_key = options.fetch(:api_key) { raise ArgumentError.new(":api_key is a required argument to initialize Mailgun") if Mailgun.api_key.nil?}
|
16
|
-
Mailgun.domain = options.fetch(:domain)
|
16
|
+
Mailgun.domain = options.fetch(:domain) { nil }
|
17
17
|
end
|
18
18
|
|
19
19
|
# Returns the base url used in all Mailgun API calls
|
@@ -29,15 +29,15 @@ module Mailgun
|
|
29
29
|
def messages(domain = Mailgun.domain)
|
30
30
|
@messages ||= Mailgun::Message.new(self, domain)
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def routes
|
34
34
|
@routes ||= Mailgun::Route.new(self)
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def bounces(domain = Mailgun.domain)
|
38
38
|
Mailgun::Bounce.new(self, domain)
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
def domains
|
42
42
|
Mailgun::Domain.new(self)
|
43
43
|
end
|
data/lib/mailgun/bounce.rb
CHANGED
@@ -10,17 +10,38 @@ module Mailgun
|
|
10
10
|
end
|
11
11
|
|
12
12
|
# List all bounces for a given domain
|
13
|
+
#
|
14
|
+
# @param options [Hash] options to populate to mailgun find
|
15
|
+
# @option options limit (100) [Integer] limit of results
|
16
|
+
# @option options skip (0) [Integer] number of results to skip
|
17
|
+
#
|
18
|
+
# @returns [Array<Hash>] array of bouces
|
13
19
|
def list(options={})
|
14
20
|
Mailgun.submit(:get, bounce_url, options)["items"] || []
|
15
21
|
end
|
16
22
|
|
17
23
|
# Find bounce events for an email address
|
24
|
+
#
|
25
|
+
# @returns [<Hash>] found bouce
|
18
26
|
def find(email)
|
19
27
|
Mailgun.submit :get, bounce_url(email)
|
20
28
|
end
|
21
29
|
|
22
|
-
|
23
|
-
|
30
|
+
# Creates a bounce for an email address
|
31
|
+
#
|
32
|
+
# @param email [String] email address to bounce
|
33
|
+
# @param options [Hash] options to populate to mailgun bounce creation
|
34
|
+
# @option options code (550) [Integer] Error code
|
35
|
+
# @option options error ('') [String] Error description
|
36
|
+
#
|
37
|
+
# @returns [<Hash>] created bouce
|
38
|
+
def add(email, options={})
|
39
|
+
Mailgun.submit :post, bounce_url, {:address => email}.merge(options)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Cleans the bounces for an email address
|
43
|
+
def destroy(email)
|
44
|
+
Mailgun.submit :delete, bounce_url(email)
|
24
45
|
end
|
25
46
|
|
26
47
|
private
|
@@ -31,4 +52,4 @@ module Mailgun
|
|
31
52
|
end
|
32
53
|
|
33
54
|
end
|
34
|
-
end
|
55
|
+
end
|
data/lib/mailgun/message.rb
CHANGED
@@ -8,7 +8,7 @@ module Mailgun
|
|
8
8
|
# send email
|
9
9
|
def send_email(parameters={})
|
10
10
|
# options:
|
11
|
-
# :from, :to, :cc, :bcc, :subject, :text, :html
|
11
|
+
# :from, :to, :cc, :bcc, :subject, :text, :html
|
12
12
|
# :with_attachment
|
13
13
|
# :with_attachments
|
14
14
|
# :at for delayed delivery time option
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Joshua Peek
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,16 @@
|
|
1
|
+
= Multimap
|
2
|
+
|
3
|
+
A Ruby multimap implementation that also includes multiset and nested multimap implementations.
|
4
|
+
|
5
|
+
== Example
|
6
|
+
|
7
|
+
require 'multimap'
|
8
|
+
|
9
|
+
map = Multimap.new
|
10
|
+
map["a"] = 100
|
11
|
+
map["b"] = 200
|
12
|
+
map["a"] = 300
|
13
|
+
|
14
|
+
map["a"] # -> [100, 300]
|
15
|
+
map["b"] # -> [200]
|
16
|
+
map.keys # -> #<Multiset: {"a", "a", "b"}>
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rubygems/specification'
|
2
|
+
spec = eval(File.read('multimap.gemspec'))
|
3
|
+
|
4
|
+
if spec.has_rdoc
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
|
7
|
+
Rake::RDocTask.new { |rdoc|
|
8
|
+
rdoc.options = spec.rdoc_options
|
9
|
+
rdoc.rdoc_files = spec.files
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
task :default => :spec
|
15
|
+
|
16
|
+
require 'spec/rake/spectask'
|
17
|
+
|
18
|
+
Spec::Rake::SpecTask.new do |t|
|
19
|
+
t.warning = true
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
begin
|
24
|
+
require 'rake/extensiontask'
|
25
|
+
|
26
|
+
Rake::ExtensionTask.new do |ext|
|
27
|
+
ext.name = 'nested_multimap_ext'
|
28
|
+
ext.gem_spec = $spec
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "Run specs using C ext"
|
32
|
+
task "spec:ext" => [:compile, :spec, :clobber]
|
33
|
+
rescue LoadError
|
34
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
$: << 'lib'
|
2
|
+
require 'nested_multimap'
|
3
|
+
|
4
|
+
tiny_mapping = {
|
5
|
+
["a"] => 100
|
6
|
+
}
|
7
|
+
|
8
|
+
medium_mapping = {
|
9
|
+
["a"] => 100,
|
10
|
+
["a", "b", "c"] => 200,
|
11
|
+
["b"] => 300,
|
12
|
+
["b", "c"] => 400,
|
13
|
+
["c"] => 500,
|
14
|
+
["c", "d"] => 600,
|
15
|
+
["c", "d", "e"] => 700,
|
16
|
+
["c", "d", "e", "f"] => 800
|
17
|
+
}
|
18
|
+
|
19
|
+
huge_mapping = {}
|
20
|
+
alpha = ("a".."zz").to_a
|
21
|
+
100.times do |n|
|
22
|
+
keys = ("a"..alpha[n % alpha.length]).to_a
|
23
|
+
huge_mapping[keys] = n * 100
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'benchmark'
|
27
|
+
|
28
|
+
Benchmark.bmbm do |x|
|
29
|
+
x.report("base:") {
|
30
|
+
NestedMultimap.new
|
31
|
+
}
|
32
|
+
|
33
|
+
x.report("tiny:") {
|
34
|
+
map = NestedMultimap.new
|
35
|
+
tiny_mapping.each_pair { |keys, value|
|
36
|
+
map[*keys] = value
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
x.report("medium:") {
|
41
|
+
map = NestedMultimap.new
|
42
|
+
medium_mapping.each_pair { |keys, value|
|
43
|
+
map[*keys] = value
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
x.report("huge:") {
|
48
|
+
map = NestedMultimap.new
|
49
|
+
huge_mapping.each_pair { |keys, value|
|
50
|
+
map[*keys] = value
|
51
|
+
}
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
# Pure Ruby
|
56
|
+
# user system total real
|
57
|
+
# base: 0.000000 0.000000 0.000000 ( 0.000014)
|
58
|
+
# tiny: 0.000000 0.000000 0.000000 ( 0.000054)
|
59
|
+
# medium: 0.000000 0.000000 0.000000 ( 0.000186)
|
60
|
+
# huge: 0.050000 0.000000 0.050000 ( 0.051302)
|
@@ -0,0 +1,33 @@
|
|
1
|
+
$: << 'lib'
|
2
|
+
require 'nested_multimap'
|
3
|
+
|
4
|
+
hash = { "a" => true }
|
5
|
+
|
6
|
+
map = NestedMultimap.new
|
7
|
+
map["a"] = 100
|
8
|
+
map["a", "b", "c"] = 200
|
9
|
+
map["a", "b", "c", "d", "e", "f"] = 300
|
10
|
+
|
11
|
+
require 'benchmark'
|
12
|
+
|
13
|
+
TIMES = 100_000
|
14
|
+
Benchmark.bmbm do |x|
|
15
|
+
x.report("base:") { TIMES.times { hash["a"] } }
|
16
|
+
x.report("best:") { TIMES.times { map["a"] } }
|
17
|
+
x.report("average:") { TIMES.times { map["a", "b", "c"] } }
|
18
|
+
x.report("worst:") { TIMES.times { map["a", "b", "c", "d", "e", "f"] } }
|
19
|
+
end
|
20
|
+
|
21
|
+
# Pure Ruby
|
22
|
+
# user system total real
|
23
|
+
# base: 0.050000 0.000000 0.050000 ( 0.049722)
|
24
|
+
# best: 0.480000 0.010000 0.490000 ( 0.491012)
|
25
|
+
# average: 0.770000 0.000000 0.770000 ( 0.773535)
|
26
|
+
# worst: 1.120000 0.010000 1.130000 ( 1.139097)
|
27
|
+
|
28
|
+
# C extension
|
29
|
+
# user system total real
|
30
|
+
# base: 0.050000 0.000000 0.050000 ( 0.050990)
|
31
|
+
# best: 0.090000 0.000000 0.090000 ( 0.088981)
|
32
|
+
# average: 0.130000 0.000000 0.130000 ( 0.132098)
|
33
|
+
# worst: 0.150000 0.000000 0.150000 ( 0.158293)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
|
3
|
+
VALUE cNestedMultimap;
|
4
|
+
|
5
|
+
static VALUE rb_nested_multimap_aref(int argc, VALUE *argv, VALUE self)
|
6
|
+
{
|
7
|
+
int i;
|
8
|
+
VALUE r, h;
|
9
|
+
|
10
|
+
for (i = 0, r = self; rb_obj_is_kind_of(r, cNestedMultimap) == Qtrue; i++) {
|
11
|
+
h = rb_funcall(r, rb_intern("_internal_hash"), 0);
|
12
|
+
Check_Type(h, T_HASH);
|
13
|
+
r = (i < argc) ? rb_hash_aref(h, argv[i]) : RHASH(h)->ifnone;
|
14
|
+
}
|
15
|
+
|
16
|
+
return r;
|
17
|
+
}
|
18
|
+
|
19
|
+
void Init_nested_multimap_ext() {
|
20
|
+
cNestedMultimap = rb_const_get(rb_cObject, rb_intern("NestedMultimap"));
|
21
|
+
// rb_funcall(cNestedMultimap, rb_intern("remove_method"), 1, rb_intern("[]"));
|
22
|
+
rb_eval_string("NestedMultimap.send(:remove_method, :[])");
|
23
|
+
rb_define_method(cNestedMultimap, "[]", rb_nested_multimap_aref, -1);
|
24
|
+
}
|