bounce_studio_ffi 0.0.1 → 0.1.1
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 +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +21 -3
- data/Rakefile +10 -0
- data/bounce_studio_ffi.gemspec +2 -2
- data/lib/bounce_studio_ffi/version.rb +1 -1
- data/lib/bounce_studio_ffi.rb +11 -33
- data/test/bouncestudio_test.rb +99 -0
- data/test/raw_message.txt +50 -0
- data/test/test_helper.rb +9 -0
- metadata +11 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a67c70ab38153699c64aacffa59e9650f9f1b0c9
|
4
|
+
data.tar.gz: 1cd49f1a70faff6ba40c9d609a2db6aad824339e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57ff9c4d8299b238f4ccd19a8eecb87def1e0b762a8311f0351113741927cc1b0b037349504160cdbd2bec624fffefcbe1e163cb444eb73ad1047df4fe404879
|
7
|
+
data.tar.gz: 43120b862f6f3110a2a748a2be5c8f64248f07b45d1b0b0c9f4f86b4ed137829b54fc89cdac03c39512a61c4294c12fc87e0d618e041a0fe42f35478166dcac2
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,9 +1,17 @@
|
|
1
|
-
#
|
1
|
+
# bounce\_studio\_ffi
|
2
2
|
|
3
|
-
|
3
|
+
A Ruby FFI binding for the (commercial) [BounceStudio API 3.7 for Linux](http://www.boogietools.com/Products/Linux/). Designed to be compatible with the included native extension.
|
4
|
+
|
5
|
+
## Requirements
|
6
|
+
|
7
|
+
* FFI-supporting Ruby 1.9+ (MRI/JRuby)
|
8
|
+
* Linux
|
9
|
+
* BounceStudio API libs
|
4
10
|
|
5
11
|
## Installation
|
6
12
|
|
13
|
+
Follow [these installation instructions](http://www.boogietools.com/Products/Linux/BounceStudioAPI/help/files/installation.html) to install the C API library.
|
14
|
+
|
7
15
|
Add this line to your application's Gemfile:
|
8
16
|
|
9
17
|
gem 'bounce_studio_ffi'
|
@@ -18,7 +26,17 @@ Or install it yourself as:
|
|
18
26
|
|
19
27
|
## Usage
|
20
28
|
|
21
|
-
|
29
|
+
# 32-bit lib is used by default; set ENV['BOUNCE_STUDIO_MODE'] to 64 to use 64-bit lib before requiring
|
30
|
+
require 'bounce_studio_ffi'
|
31
|
+
BS_LICENSE = "Foobar/1234567890"
|
32
|
+
bs = BoogieTools::BounceStudio.new(BS_LICENSE)
|
33
|
+
bs.check(raw_message_text)
|
34
|
+
|
35
|
+
# all functions documented at http://www.boogietools.com/Products/Linux/BounceStudioAPI/help/help.html
|
36
|
+
# are supported, e.g.
|
37
|
+
bs.subject(raw_message_text)
|
38
|
+
bs.orig_custom_header(raw_message_text, 'x-subscriber')
|
39
|
+
|
22
40
|
|
23
41
|
## Contributing
|
24
42
|
|
data/Rakefile
CHANGED
data/bounce_studio_ffi.gemspec
CHANGED
@@ -20,6 +20,6 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
22
|
spec.add_development_dependency "rake"
|
23
|
-
spec.
|
24
|
-
spec.
|
23
|
+
spec.add_runtime_dependency "ffi"
|
24
|
+
spec.add_runtime_dependency "activesupport"
|
25
25
|
end
|
data/lib/bounce_studio_ffi.rb
CHANGED
@@ -6,23 +6,23 @@ module BoogieTools
|
|
6
6
|
class BounceStudio
|
7
7
|
module BounceStudioLib
|
8
8
|
extend FFI::Library
|
9
|
-
ffi_lib "
|
9
|
+
ffi_lib "libBounceStudio#{ENV['BOUNCE_STUDIO_MODE'] || '32'}.so"
|
10
10
|
attach_function :bsBounceStudio_init, [], :int
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
STRING_OUTPUT_METHODS = [:header, :subject, :body, :to_address, :to_friendly_name, :reply_to_address, :reply_to_friendly_name, :from_address, :from_friendly_name].freeze
|
13
|
+
STRING_OUTPUT_METHODS.each do |ruby_method_name|
|
14
14
|
attach_function :"bsGet#{ruby_method_name.to_s.camelize}", [:string, :pointer], :void
|
15
15
|
end
|
16
|
-
attach_function :bsBounceCheck, [:string, :pointer, :string, :string], :int
|
17
16
|
|
18
17
|
CUSTOM_HEADER_METHODS = [:custom_header, :orig_custom_header].freeze
|
19
18
|
CUSTOM_HEADER_METHODS.each do |ruby_method_name|
|
20
19
|
attach_function :"bsGet#{ruby_method_name.to_s.camelize}", [:string, :pointer, :string], :void
|
21
20
|
end
|
22
21
|
|
23
|
-
attach_function :
|
22
|
+
attach_function :bsBounceCheck, [:string, :pointer, :string, :string], :int
|
24
23
|
end
|
25
24
|
|
25
|
+
# gotta call this before we do anything
|
26
26
|
BounceStudioLib.bsBounceStudio_init
|
27
27
|
|
28
28
|
attr_accessor :license
|
@@ -30,7 +30,7 @@ module BoogieTools
|
|
30
30
|
self.license=license
|
31
31
|
end
|
32
32
|
|
33
|
-
BounceStudioLib::
|
33
|
+
BounceStudioLib::STRING_OUTPUT_METHODS.each do |ruby_method_name|
|
34
34
|
define_method ruby_method_name do |raw_message|
|
35
35
|
string_output do |ptr|
|
36
36
|
BounceStudioLib.send(:"bsGet#{ruby_method_name.to_s.camelize}", raw_message, ptr)
|
@@ -44,13 +44,13 @@ module BoogieTools
|
|
44
44
|
BounceStudioLib.send(:"bsGet#{ruby_method_name.to_s.camelize}", raw_message, ptr, header_name)
|
45
45
|
end
|
46
46
|
end
|
47
|
-
end
|
48
|
-
|
47
|
+
end
|
49
48
|
|
50
|
-
|
49
|
+
# ignore list is pipe-delimited string of email addresses
|
50
|
+
def check(raw_message, ignore_list='')
|
51
51
|
code = nil
|
52
52
|
string_output do |ptr|
|
53
|
-
code = BounceStudioLib.bsBounceCheck(raw_message, ptr,
|
53
|
+
code = BounceStudioLib.bsBounceCheck(raw_message, ptr, ignore_list, self.license)
|
54
54
|
end
|
55
55
|
return code
|
56
56
|
end
|
@@ -66,26 +66,4 @@ module BoogieTools
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
-
end
|
70
|
-
|
71
|
-
|
72
|
-
{
|
73
|
-
:BS_UNDETERMINED => 0, # Undetermined
|
74
|
-
:BS_HARD => 10, # HARD BOUNCE
|
75
|
-
:BS_SOFT_GENERAL => 20, # SOFT BOUNCE - General
|
76
|
-
:BS_SOFT_DNSFAILURE => 21, # SOFT BOUNCE - Dns Failure
|
77
|
-
:BS_SOFT_MAILBOXFULL => 22, # SOFT BOUNCE - Mailbox Full
|
78
|
-
:BS_SOFT_MESSAGETOBIG => 23, # SOFT BOUNCE - Message Size Too Large
|
79
|
-
:BS_NOEMAIL => 30, # BOUNCE - email address could not be retrieved.
|
80
|
-
:BS_GENERAL => 40, # GENERAL BOUNCE
|
81
|
-
:BS_MAILBLOCK_GENERAL => 50, # MAIL BLOCK - General
|
82
|
-
:BS_MAILBLOCK_SPAMMER => 51, # MAIL BLOCK - Known Spammer
|
83
|
-
:BS_MAILBLOCK_SPAMDETECTED => 52, # MAIL BLOCK - Spam Content Detected
|
84
|
-
:BS_MAILBLOCK_ATTACHMENT => 53, # MAIL BLOCK - Attachment Detected
|
85
|
-
:BS_MAILBLOCK_RELAYDENIED => 54, # MAIL BLOCK - Relay Denied
|
86
|
-
:BS_AUTOREPLY => 60, # AUTO REPLY
|
87
|
-
:BS_TRANSIENT => 70, # TRANSIENT BOUNCE
|
88
|
-
:BS_SUBSCRIBE => 80, # SUBSCRIBE REQUEST
|
89
|
-
:BS_UNSUBSCRIBE => 90, # UNSUBSCRIBE REQUEST
|
90
|
-
:BS_CHALLENGERESPONSE =>100, # CHALLENGE-RESPONSE MESSAGE
|
91
|
-
}
|
69
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class BounceStudioTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
license_code = BS_LICENSE
|
7
|
+
@studio = BoogieTools::BounceStudio.new license_code
|
8
|
+
@raw = IO.read File.join(File.dirname(__FILE__), "raw_message.txt")
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_truth
|
12
|
+
assert true
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_studio_type
|
16
|
+
assert_equal Object, BoogieTools::BounceStudio.superclass
|
17
|
+
assert_equal BoogieTools::BounceStudio, @studio.class
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_check
|
21
|
+
bounce_code = @studio.check(@raw)
|
22
|
+
assert bounce_code.is_a?(Fixnum)
|
23
|
+
assert_equal bounce_code, 10
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_body
|
27
|
+
body = @studio.body(@raw)
|
28
|
+
assert body.is_a?(String)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_from_address
|
32
|
+
from_address = @studio.from_address(@raw)
|
33
|
+
assert from_address.is_a?(String)
|
34
|
+
assert !from_address.empty?
|
35
|
+
assert_equal from_address, "MAILER-DAEMON@mail.coinet.com".downcase
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_from_friendly_name
|
39
|
+
from_friendly_name = @studio.from_friendly_name(@raw)
|
40
|
+
assert from_friendly_name.is_a?(String)
|
41
|
+
assert from_friendly_name.empty?
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_header
|
45
|
+
header = @studio.header(@raw)
|
46
|
+
assert header.is_a?(String)
|
47
|
+
assert !header.empty?
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_reply_to_address
|
51
|
+
reply_to_address = @studio.reply_to_address(@raw)
|
52
|
+
assert reply_to_address.is_a?(String)
|
53
|
+
assert reply_to_address.empty?
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_reply_to_friendly_name
|
57
|
+
reply_to_friendly_name = @studio.reply_to_friendly_name(@raw)
|
58
|
+
assert reply_to_friendly_name.is_a?(String)
|
59
|
+
assert reply_to_friendly_name.empty?
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_subject
|
63
|
+
subject = @studio.subject(@raw)
|
64
|
+
assert subject.is_a?(String)
|
65
|
+
assert !subject.empty?
|
66
|
+
assert_equal subject.chomp, "failure notice"
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_to_address
|
70
|
+
to_address = @studio.to_address(@raw)
|
71
|
+
assert to_address.is_a?(String)
|
72
|
+
assert !to_address.empty?
|
73
|
+
assert_equal to_address, "joebob@joe.net"
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_to_friendly_name
|
77
|
+
to_friendly_name = @studio.to_friendly_name(@raw)
|
78
|
+
assert to_friendly_name.is_a?(String)
|
79
|
+
assert to_friendly_name.empty?
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_custom_header
|
83
|
+
custom_header = @studio.custom_header(@raw, "X-OriginalArrivalTime".downcase)
|
84
|
+
assert custom_header.is_a?(String)
|
85
|
+
assert custom_header.empty?
|
86
|
+
|
87
|
+
date_header = @studio.custom_header(@raw, "Date".downcase)
|
88
|
+
assert date_header.is_a?(String)
|
89
|
+
assert !date_header.empty?
|
90
|
+
assert_equal date_header.chomp, "21 Aug 2000 21:08:21 -0000"
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_orig_custom_header
|
94
|
+
orig_custom_header = @studio.orig_custom_header(@raw, "X-OriginalArrivalTime".downcase)
|
95
|
+
assert orig_custom_header.is_a?(String)
|
96
|
+
assert !orig_custom_header.empty?
|
97
|
+
assert_equal orig_custom_header.chomp, "21 Aug 2000 21:08:20.0944 (UTC) FILETIME=[EF5F8500:01C00BB3]"
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
Return-Path: <>
|
3
|
+
Received: from defiant.coinet.com ([204.245.234.17])
|
4
|
+
by detmail.somedomain.net (Post.Office MTA v3.5.3 release 223
|
5
|
+
ID# 0-65382U1000L100S0V35) with SMTP id net
|
6
|
+
for <joebob@joe.net>; Mon, 21 Aug 2000 14:07:48 -0700
|
7
|
+
Received: (qmail 849 invoked for bounce); 21 Aug 2000 21:08:21 -0000
|
8
|
+
Date: 21 Aug 2000 21:08:21 -0000
|
9
|
+
From: MAILER-DAEMON@mail.coinet.com
|
10
|
+
To: joebob@joe.net
|
11
|
+
Subject: failure notice
|
12
|
+
|
13
|
+
Hi. This is the mail transport agent at mail.coinet.com.
|
14
|
+
I'm afraid I wasn't able to deliver your message to the following addresses.
|
15
|
+
This is a permanent error; I've given up. If you have questions about this
|
16
|
+
notice, please forward it to postmaster@coinet.com along with your comments.
|
17
|
+
|
18
|
+
<wolfden@coinet.com>:
|
19
|
+
Sorry, this account has been deactivated. (#5.2.1)
|
20
|
+
|
21
|
+
--- Below this line is a copy of the message.
|
22
|
+
|
23
|
+
Return-Path: <joebob@joe.net>
|
24
|
+
Received: (qmail 841 invoked from network); 21 Aug 2000 21:08:21 -0000
|
25
|
+
Received: from pool104.somedomain.com (HELO detcmail02.somedomain.net) (1.2.3.4)
|
26
|
+
by coinet.com with SMTP; 21 Aug 2000 21:08:21 -0000
|
27
|
+
Received: from detcmail02 ([2.3.4.5]) by detcmail02.somedomain.net with Microsoft SMTPSVC(5.0.2172.1);
|
28
|
+
Mon, 21 Aug 2000 14:08:20 -0700
|
29
|
+
From: "JOE.NET" <joebob@joe.net>
|
30
|
+
Reply-To: "JOE.NET" <some_reply@joe.net>
|
31
|
+
To: <wolfden@coinet.com>
|
32
|
+
Date: Mon, 21 Aug 00 14:08:20 -0700
|
33
|
+
Subject: JOE.NET NEWS!
|
34
|
+
MIME-Version: 1.0
|
35
|
+
Content-Type: multipart/alternative; boundary="----_=_Send_NextPart_180_03281976"
|
36
|
+
Return-Path: joebob@joe.net
|
37
|
+
Message-ID: <DETCMAIL02agW2wx6Di000110f7@DETcmail02.somedomain.net>
|
38
|
+
X-OriginalArrivalTime: 21 Aug 2000 21:08:20.0944 (UTC) FILETIME=[EF5F8500:01C00BB3]
|
39
|
+
|
40
|
+
This is a multi-part message in MIME format.
|
41
|
+
|
42
|
+
|
43
|
+
------_=_Send_NextPart_180_03281976
|
44
|
+
Content-Type: text/plain; charset=us-ascii
|
45
|
+
|
46
|
+
Here's my test message. This is the body of the message.... Cool.... Okay, bye!
|
47
|
+
|
48
|
+
.
|
49
|
+
|
50
|
+
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/bounce_studio_ffi'
|
3
|
+
if ENV['BS_LICENSE']
|
4
|
+
BS_LICENSE = ENV['BS_LICENSE']
|
5
|
+
else
|
6
|
+
puts "Set the environment variable BS_LICENSE with your BoogieTools license code to avoid tarpit"
|
7
|
+
BS_LICENSE = "nolicense"
|
8
|
+
end
|
9
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bounce_studio_ffi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benjamin Ortega
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-10-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -45,7 +45,7 @@ dependencies:
|
|
45
45
|
- - '>='
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
|
-
type: :
|
48
|
+
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
@@ -59,7 +59,7 @@ dependencies:
|
|
59
59
|
- - '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
|
-
type: :
|
62
|
+
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
@@ -81,6 +81,9 @@ files:
|
|
81
81
|
- bounce_studio_ffi.gemspec
|
82
82
|
- lib/bounce_studio_ffi.rb
|
83
83
|
- lib/bounce_studio_ffi/version.rb
|
84
|
+
- test/bouncestudio_test.rb
|
85
|
+
- test/raw_message.txt
|
86
|
+
- test/test_helper.rb
|
84
87
|
homepage: ''
|
85
88
|
licenses:
|
86
89
|
- MIT
|
@@ -105,4 +108,7 @@ rubygems_version: 2.0.3
|
|
105
108
|
signing_key:
|
106
109
|
specification_version: 4
|
107
110
|
summary: FFI wrapper for Ruby BounceStudio API for Linux
|
108
|
-
test_files:
|
111
|
+
test_files:
|
112
|
+
- test/bouncestudio_test.rb
|
113
|
+
- test/raw_message.txt
|
114
|
+
- test/test_helper.rb
|