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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d55f124f1986f1abe6d236ab361d17f987608bca
4
- data.tar.gz: 1d097c1e1770441598efca0cde85b616e140cdd4
3
+ metadata.gz: a67c70ab38153699c64aacffa59e9650f9f1b0c9
4
+ data.tar.gz: 1cd49f1a70faff6ba40c9d609a2db6aad824339e
5
5
  SHA512:
6
- metadata.gz: 175869132a2b373dafbd52500eddf9411d7935b1b4c5b901b37660beff963d334868323baded564fdbe4d8fa26297743595b87e1e336fa6ba0db5d3c56b03694
7
- data.tar.gz: 9f982c438bc41ed6b591fc2b52321efef1612e81f6fff29e0759538cb28d82f9339bc7b3d70632467ef96bf43c36e51090c2605e7578b63ffb78dba0ee675d8d
6
+ metadata.gz: 57ff9c4d8299b238f4ccd19a8eecb87def1e0b762a8311f0351113741927cc1b0b037349504160cdbd2bec624fffefcbe1e163cb444eb73ad1047df4fe404879
7
+ data.tar.gz: 43120b862f6f3110a2a748a2be5c8f64248f07b45d1b0b0c9f4f86b4ed137829b54fc89cdac03c39512a61c4294c12fc87e0d618e041a0fe42f35478166dcac2
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013 TODO: Write your name
1
+ Copyright (c) 2013 Benjamin Ortega
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -1,9 +1,17 @@
1
- # BounceStudioFfi
1
+ # bounce\_studio\_ffi
2
2
 
3
- TODO: Write a gem description
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
- TODO: Write usage instructions here
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
@@ -1 +1,11 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+
5
+ desc('Runs all tests in the subdirectories of lib')
6
+ task :test do
7
+ Rake::TestTask.new do |t|
8
+ t.libs << 'test'
9
+ t.pattern = 'test/**/*_test.rb'
10
+ end
11
+ end
@@ -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.add_development_dependency "ffi"
24
- spec.add_development_dependency "activesupport"
23
+ spec.add_runtime_dependency "ffi"
24
+ spec.add_runtime_dependency "activesupport"
25
25
  end
@@ -1,3 +1,3 @@
1
1
  module BounceStudioFfi
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -6,23 +6,23 @@ module BoogieTools
6
6
  class BounceStudio
7
7
  module BounceStudioLib
8
8
  extend FFI::Library
9
- ffi_lib "libBounceStudio32.so"
9
+ ffi_lib "libBounceStudio#{ENV['BOUNCE_STUDIO_MODE'] || '32'}.so"
10
10
  attach_function :bsBounceStudio_init, [], :int
11
11
 
12
- STRING_POINTER_METHODS = [:header, :subject, :body, :to_address, :to_friendly_name, :reply_to_address, :reply_to_friendly_name, :from_address, :from_friendly_name].freeze
13
- STRING_POINTER_METHODS.each do |ruby_method_name|
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 :bsGetOrigCustomHeader, [:string, :pointer, :string], :void
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::STRING_POINTER_METHODS.each do |ruby_method_name|
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
- def check(raw_message)
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, 'asdasd@sss.com', self.license)
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
+
@@ -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.0.1
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-08-23 00:00:00.000000000 Z
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: :development
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: :development
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