paubox 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
-
4
- RSpec::Core::RakeTask.new(:spec)
5
-
6
- task :default => :spec
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -1,14 +1,15 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "paubox_ruby"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start(__FILE__)
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'paubox_ruby'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require 'irb'
15
+ IRB.start(__FILE__)
data/bin/setup CHANGED
@@ -1,8 +1,8 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -1,19 +1,21 @@
1
- module Mail
2
- class Paubox
3
- attr_accessor :settings
4
-
5
- def initialize(settings)
6
- @settings = settings
7
- end
8
-
9
- def deliver!(mail)
10
- client = ::Paubox::Client.new(settings)
11
- response = client.send_mail(mail)
12
- puts response
13
- end
14
- end
15
-
16
- class Message
17
- attr_accessor :source_tracking_id, :status, :allow_non_tls
18
- end
19
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Mail
4
+ class Paubox
5
+ attr_accessor :settings
6
+
7
+ def initialize(settings)
8
+ @settings = settings
9
+ end
10
+
11
+ def deliver!(mail)
12
+ client = ::Paubox::Client.new(settings)
13
+ response = client.send_mail(mail)
14
+ puts response
15
+ end
16
+ end
17
+
18
+ class Message
19
+ attr_accessor :source_tracking_id, :status, :allow_non_tls, :force_secure_notification
20
+ end
21
+ end
@@ -1,22 +1,24 @@
1
- require 'paubox/version'
2
- require 'paubox/client'
3
- require 'paubox/format_helper'
4
- require 'paubox/mail_to_message'
5
- require 'paubox/message'
6
- require 'paubox/email_disposition'
7
- require 'mail/paubox'
8
-
9
- module Paubox
10
- class << self
11
- attr_accessor :configuration
12
- end
13
-
14
- def self.configure
15
- self.configuration ||= Configuration.new
16
- yield(configuration)
17
- end
18
-
19
- class Configuration
20
- attr_accessor :api_key, :api_user
21
- end
22
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'paubox/version'
4
+ require 'paubox/client'
5
+ require 'paubox/format_helper'
6
+ require 'paubox/mail_to_message'
7
+ require 'paubox/message'
8
+ require 'paubox/email_disposition'
9
+ require 'mail/paubox'
10
+
11
+ module Paubox
12
+ class << self
13
+ attr_accessor :configuration
14
+ end
15
+
16
+ def self.configure
17
+ self.configuration ||= Configuration.new
18
+ yield(configuration)
19
+ end
20
+
21
+ class Configuration
22
+ attr_accessor :api_key, :api_user
23
+ end
24
+ end
@@ -1,81 +1,85 @@
1
- module Paubox
2
- # Client sends API requests to Paubox API
3
- class Client
4
- require 'rest-client'
5
- require 'ostruct'
6
- attr_reader :api_key, :api_user, :api_host, :api_protocol, :api_version
7
-
8
- def initialize(args = {})
9
- args = defaults.merge(args)
10
- @api_key = args[:api_key]
11
- @api_user = args[:api_user]
12
- @api_host = args[:api_host]
13
- @api_protocol = args[:api_protocol]
14
- @api_version = args[:api_version]
15
- @test_mode = args[:test_mode]
16
- @api_base_endpoint = api_base_endpoint
17
- @allow_non_tls = args.fetch(:allow_non_tls, false)
18
- end
19
-
20
- def api_status
21
- url = request_endpoint('status')
22
- RestClient.get(url, accept: :json)
23
- end
24
-
25
- def send_mail(mail)
26
- case mail
27
- when Mail::Message
28
- payload = MailToMessage.new(mail, { allow_non_tls: @allow_non_tls })
29
- .send_message_payload
30
- when Hash
31
- payload = Message.new(mail).send_message_payload
32
- end
33
- url = request_endpoint('messages')
34
- response = RestClient.post(url, payload, auth_header)
35
- if mail.class == Mail::Message
36
- mail.source_tracking_id = JSON.parse(response.body)['sourceTrackingId']
37
- end
38
- JSON.parse(response.body)
39
- end
40
- alias deliver_mail send_mail
41
-
42
- def email_disposition(source_tracking_id)
43
- url = "#{request_endpoint('message_receipt')}?sourceTrackingId=#{source_tracking_id}"
44
- response = RestClient.get(url, auth_header)
45
- email_disposition = Paubox::EmailDisposition.new(JSON.parse(response.body))
46
- end
47
- alias message_receipt email_disposition
48
-
49
- private
50
-
51
- def auth_header
52
- { accept: :json,
53
- content_type: :json,
54
- :Authorization => "Token token=#{@api_key}" }
55
- end
56
-
57
- def api_base_endpoint
58
- "#{api_protocol}#{api_host}/#{api_version}/#{api_user}"
59
- end
60
-
61
- def request_endpoint(endpoint)
62
- "#{api_base_endpoint}/#{endpoint}"
63
- end
64
-
65
- def defaults
66
- { api_key: Paubox.configuration.api_key,
67
- api_user: Paubox.configuration.api_user,
68
- api_host: 'api.paubox.net',
69
- api_protocol: 'https://',
70
- api_version: 'v1',
71
- test_mode: false }
72
- end
73
-
74
- # recursively converts a nested Hash into OpenStruct
75
- def to_open_struct(hash)
76
- OpenStruct.new(hash.each_with_object({}) do |(key, val), memo|
77
- memo[key] = val.is_a?(Hash) ? to_open_struct(val) : val
78
- end)
79
- end
80
- end
81
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Paubox
4
+ # Client sends API requests to Paubox API
5
+ class Client
6
+ require 'rest-client'
7
+ require 'ostruct'
8
+ attr_reader :api_key, :api_user, :api_host, :api_protocol, :api_version
9
+
10
+ def initialize(args = {})
11
+ args = defaults.merge(args)
12
+ @api_key = args[:api_key]
13
+ @api_user = args[:api_user]
14
+ @api_host = args[:api_host]
15
+ @api_protocol = args[:api_protocol]
16
+ @api_version = args[:api_version]
17
+ @test_mode = args[:test_mode]
18
+ @api_base_endpoint = api_base_endpoint
19
+ end
20
+
21
+ def api_status
22
+ url = request_endpoint('status')
23
+ RestClient.get(url, accept: :json)
24
+ end
25
+
26
+ def send_mail(mail)
27
+ case mail
28
+ when Mail::Message
29
+ allow_non_tls = mail.allow_non_tls.nil? ? false : mail.allow_non_tls
30
+ payload = MailToMessage.new(mail, allow_non_tls: allow_non_tls)
31
+ .send_message_payload
32
+ when Hash
33
+ payload = Message.new(mail).send_message_payload
34
+ when Paubox::Message
35
+ payload = mail.send_message_payload
36
+ end
37
+ url = request_endpoint('messages')
38
+ response = RestClient.post(url, payload, auth_header)
39
+ if mail.class == Mail::Message
40
+ mail.source_tracking_id = JSON.parse(response.body)['sourceTrackingId']
41
+ end
42
+ JSON.parse(response.body)
43
+ end
44
+ alias deliver_mail send_mail
45
+
46
+ def email_disposition(source_tracking_id)
47
+ url = "#{request_endpoint('message_receipt')}?sourceTrackingId=#{source_tracking_id}"
48
+ response = RestClient.get(url, auth_header)
49
+ email_disposition = Paubox::EmailDisposition.new(JSON.parse(response.body))
50
+ end
51
+ alias message_receipt email_disposition
52
+
53
+ private
54
+
55
+ def auth_header
56
+ { accept: :json,
57
+ content_type: :json,
58
+ Authorization: "Token token=#{@api_key}" }
59
+ end
60
+
61
+ def api_base_endpoint
62
+ "#{api_protocol}#{api_host}/#{api_version}/#{api_user}"
63
+ end
64
+
65
+ def request_endpoint(endpoint)
66
+ "#{api_base_endpoint}/#{endpoint}"
67
+ end
68
+
69
+ def defaults
70
+ { api_key: Paubox.configuration.api_key,
71
+ api_user: Paubox.configuration.api_user,
72
+ api_host: 'api.paubox.net',
73
+ api_protocol: 'https://',
74
+ api_version: 'v1',
75
+ test_mode: false }
76
+ end
77
+
78
+ # recursively converts a nested Hash into OpenStruct
79
+ def to_open_struct(hash)
80
+ OpenStruct.new(hash.each_with_object({}) do |(key, val), memo|
81
+ memo[key] = val.is_a?(Hash) ? to_open_struct(val) : val
82
+ end)
83
+ end
84
+ end
85
+ end
@@ -1,57 +1,62 @@
1
- module Paubox
2
- # Parses email dispositions from /v1/message_reciept response to friendly Ruby
3
- class EmailDisposition
4
- require 'time'
5
- attr_reader :response, :raw_json_response, :source_tracking_id, :message_id,
6
- :message_deliveries, :errors
7
- MessageDelivery = Struct.new(:recipient, :status)
8
- MessageDeliveryStatus = Struct.new(:delivery_status, :delivery_time,
9
- :opened_status, :opened_time)
10
- MessageMultiDeliveryStatus = Struct.new(:delivery_status, :delivery_time)
11
- ResponseError = Struct.new(:code, :status, :title, :details)
12
-
13
- def initialize(response)
14
- @response = response
15
- @raw_json_response = response.to_json
16
- @source_tracking_id = response.dig('sourceTrackingId')
17
- @message_data = response.dig('data', 'message')
18
- @message_id = @message_data ? @message_data['id'] : nil
19
- @message_deliveries ||= build_message_deliveries
20
- @errors ||= build_errors
21
- end
22
-
23
- def errors?
24
- errors.any?
25
- end
26
-
27
- def build_errors
28
- return [] unless response['errors']
29
- errors = response['errors']
30
- errors.map { |e| ResponseError.new(e['code'], e['status'], e['title'], e['details']) }
31
- end
32
-
33
- private
34
-
35
- def build_message_deliveries
36
- return [] unless @message_data
37
- deliveries = @message_data.fetch('message_deliveries', [])
38
- deliveries.map do |delivery|
39
- status = build_message_delivery_status(delivery['status'])
40
- MessageDelivery.new(delivery['recipient'], status)
41
- end
42
- end
43
-
44
- def build_message_delivery_status(stat)
45
- delivery_status = stat['deliveryStatus']
46
- delivery_time = stat['deliveryTime'].to_s.empty? ? nil : DateTime.parse(stat['deliveryTime'])
47
- opened_status = stat['openedStatus'].to_s.empty? ? 'unopened' : stat['openedStatus']
48
- opened_time = stat['openedTime'].to_s.empty? ? nil : DateTime.parse(stat['openedTime'])
49
- return MessageMultiDeliveryStatus.new(delivery_status, delivery_time) if multi_recipient?
50
- MessageDeliveryStatus.new(delivery_status, delivery_time, opened_status, opened_time)
51
- end
52
-
53
- def multi_recipient?
54
- @message_data.fetch('message_deliveries', []).length > 1
55
- end
56
- end
57
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Paubox
4
+ # Parses email dispositions from /v1/message_reciept response to friendly Ruby
5
+ class EmailDisposition
6
+ require 'time'
7
+ attr_reader :response, :raw_json_response, :source_tracking_id, :message_id,
8
+ :message_deliveries, :errors
9
+ MessageDelivery = Struct.new(:recipient, :status)
10
+ MessageDeliveryStatus = Struct.new(:delivery_status, :delivery_time,
11
+ :opened_status, :opened_time)
12
+ MessageMultiDeliveryStatus = Struct.new(:delivery_status, :delivery_time)
13
+ ResponseError = Struct.new(:code, :status, :title, :details)
14
+
15
+ def initialize(response)
16
+ @response = response
17
+ @raw_json_response = response.to_json
18
+ @source_tracking_id = response.dig('sourceTrackingId')
19
+ @message_data = response.dig('data', 'message')
20
+ @message_id = @message_data ? @message_data['id'] : nil
21
+ @message_deliveries ||= build_message_deliveries
22
+ @errors ||= build_errors
23
+ end
24
+
25
+ def errors?
26
+ errors.any?
27
+ end
28
+
29
+ def build_errors
30
+ return [] unless response['errors']
31
+
32
+ errors = response['errors']
33
+ errors.map { |e| ResponseError.new(e['code'], e['status'], e['title'], e['details']) }
34
+ end
35
+
36
+ private
37
+
38
+ def build_message_deliveries
39
+ return [] unless @message_data
40
+
41
+ deliveries = @message_data.fetch('message_deliveries', [])
42
+ deliveries.map do |delivery|
43
+ status = build_message_delivery_status(delivery['status'])
44
+ MessageDelivery.new(delivery['recipient'], status)
45
+ end
46
+ end
47
+
48
+ def build_message_delivery_status(stat)
49
+ delivery_status = stat['deliveryStatus']
50
+ delivery_time = stat['deliveryTime'].to_s.empty? ? nil : DateTime.parse(stat['deliveryTime'])
51
+ opened_status = stat['openedStatus'].to_s.empty? ? 'unopened' : stat['openedStatus']
52
+ opened_time = stat['openedTime'].to_s.empty? ? nil : DateTime.parse(stat['openedTime'])
53
+ return MessageMultiDeliveryStatus.new(delivery_status, delivery_time) if multi_recipient?
54
+
55
+ MessageDeliveryStatus.new(delivery_status, delivery_time, opened_status, opened_time)
56
+ end
57
+
58
+ def multi_recipient?
59
+ @message_data.fetch('message_deliveries', []).length > 1
60
+ end
61
+ end
62
+ end
@@ -1,55 +1,60 @@
1
- module Paubox
2
- # Utility methods for Message and MailToMessage
3
- module FormatHelper
4
- require 'base64'
5
- BASE64_REGEX = %r(/^(?:[A-Za-z0-9+\/]{4}\n?)*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/)
6
-
7
- def base64_encoded?(value)
8
- return false unless value.is_a?(String)
9
- !value.strip.match(BASE64_REGEX).nil?
10
- end
11
-
12
- def base64_encode_if_needed(str)
13
- return str if base64_encoded?(str.to_s)
14
- Base64.encode64(str.to_s)
15
- end
16
-
17
- # Converts hash keys to strings and maps them to expected JSON key.
18
- # Also converts hashes in shallow arrays.
19
- def convert_keys_to_json_version(hash)
20
- converted = {}
21
- hash.each_pair do |key, val|
22
- converted[ruby_to_json_key(key)] = val.is_a?(Hash) ? convert_keys_to_json_version(val) : val
23
- next unless val.is_a?(Array)
24
- val.each_with_index { |el, i| val[i] = convert_keys_to_json_version(el) if el.is_a?(Hash) }
25
- end
26
- converted
27
- end
28
-
29
- def ruby_to_json_key(key)
30
- { reply_to: 'reply-to', html_content: 'text/html', text_content: 'text/plain',
31
- filename: 'fileName', file_name: 'fileName', content_type: 'contentType',
32
- allow_non_tls: 'allowNonTLS' }[key] || key.to_s
33
- end
34
-
35
- # def get_values_whitelist(*vals)
36
- # vals.map { |k| next unless mail[k]; [ruby_to_json_key(k), mail[k]] }.to_h
37
- # end
38
-
39
- def string_or_array_to_array(object)
40
- case object
41
- when String
42
- a = object.split(',').map { |str| squish(str) }
43
- when Array
44
- a = object.map { |s| squish(s) }
45
- else
46
- return []
47
- end
48
- a.reject(&:empty?)
49
- end
50
-
51
- def squish(str)
52
- str.to_s.split.join(' ')
53
- end
54
- end
55
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Paubox
4
+ # Utility methods for Message and MailToMessage
5
+ module FormatHelper
6
+ require 'base64'
7
+ BASE64_REGEX = %r(/^(?:[A-Za-z0-9+\/]{4}\n?)*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/).freeze
8
+
9
+ def base64_encoded?(value)
10
+ return false unless value.is_a?(String)
11
+
12
+ !value.strip.match(BASE64_REGEX).nil?
13
+ end
14
+
15
+ def base64_encode_if_needed(str)
16
+ return str if base64_encoded?(str.to_s)
17
+
18
+ Base64.encode64(str.to_s)
19
+ end
20
+
21
+ # Converts hash keys to strings and maps them to expected JSON key.
22
+ # Also converts hashes in shallow arrays.
23
+ def convert_keys_to_json_version(hash)
24
+ converted = {}
25
+ hash.each_pair do |key, val|
26
+ converted[ruby_to_json_key(key)] = val.is_a?(Hash) ? convert_keys_to_json_version(val) : val
27
+ next unless val.is_a?(Array)
28
+
29
+ val.each_with_index { |el, i| val[i] = convert_keys_to_json_version(el) if el.is_a?(Hash) }
30
+ end
31
+ converted
32
+ end
33
+
34
+ def ruby_to_json_key(key)
35
+ { reply_to: 'reply-to', html_content: 'text/html', text_content: 'text/plain',
36
+ filename: 'fileName', file_name: 'fileName', content_type: 'contentType',
37
+ allow_non_tls: 'allowNonTLS', force_secure_notification: 'forceSecureNotification' }[key] || key.to_s
38
+ end
39
+
40
+ # def get_values_whitelist(*vals)
41
+ # vals.map { |k| next unless mail[k]; [ruby_to_json_key(k), mail[k]] }.to_h
42
+ # end
43
+
44
+ def string_or_array_to_array(object)
45
+ case object
46
+ when String
47
+ a = object.split(',').map { |str| squish(str) }
48
+ when Array
49
+ a = object.map { |s| squish(s) }
50
+ else
51
+ return []
52
+ end
53
+ a.reject(&:empty?)
54
+ end
55
+
56
+ def squish(str)
57
+ str.to_s.split.join(' ')
58
+ end
59
+ end
60
+ end