mail_plugger 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Binary file
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mail_plugger/error'
4
+ require 'mail_plugger/mail_helper'
5
+ require 'mail_plugger/delivery_method'
6
+ # If we are using this gem outside of Rails then do not load this code.
7
+ require 'mail_plugger/railtie' if defined?(Rails)
8
+ require 'mail_plugger/version'
9
+
10
+ module MailPlugger
11
+ class << self
12
+ attr_reader :delivery_options, :delivery_settings, :client
13
+
14
+ # Plug in defined API(s) class.
15
+ #
16
+ # @param [String] delivery_system the name of the API
17
+ #
18
+ # @example using Rails config/initializers/mail_plugger.rb
19
+ #
20
+ # The defined API class should have an 'initializer' and a 'deliver' method.
21
+ # class DefinedApiClientClass
22
+ # def initialize(options = {}) # required
23
+ # @settings = { api_key: ENV['API_KEY'] }
24
+ # @massage_to = options[:to]
25
+ # @message_from = options[:from]
26
+ # @message_subject = options[:subject]
27
+ # @message_body_text = options[:text_part]
28
+ # @message_body_html = options[:html_part]
29
+ # end
30
+ #
31
+ # def deliver # required
32
+ # API.new(@settings).client.post(generate_mail_hash)
33
+ # end
34
+ #
35
+ # private
36
+ #
37
+ # def generate_mail_hash
38
+ # {
39
+ # to: generate_recipients,
40
+ # from: {
41
+ # email: @message_from
42
+ # },
43
+ # subject: @message_subject,
44
+ # content: [
45
+ # {
46
+ # type: 'text/plain',
47
+ # value: @message_body_text
48
+ # },
49
+ # {
50
+ # type: 'text/html',
51
+ # value: @message_body_html
52
+ # }
53
+ # ]
54
+ # }
55
+ # end
56
+ #
57
+ # def generate_recipients
58
+ # @massage_to.map do |to|
59
+ # {
60
+ # email: to
61
+ # }
62
+ # end
63
+ # end
64
+ # end
65
+ #
66
+ # MailPlugger.plug_in('definedapi') do |api|
67
+ # # It will search these options in the Mail::Message object
68
+ # api.delivery_options = [:to, :from, :subject, :text_part, :html_part]
69
+ #
70
+ # api.client = DefinedApiClientClass
71
+ # end
72
+ #
73
+ def plug_in(delivery_system)
74
+ if delivery_system.nil? || delivery_system.strip.empty?
75
+ raise Error::WrongDeliverySystem, 'Delivery system is nil or empty. ' \
76
+ 'You should provide correct MailPlugger.plug_in parameter'
77
+ end
78
+
79
+ @delivery_system = delivery_system
80
+
81
+ yield self
82
+ rescue NoMethodError => e
83
+ raise Error::WrongPlugInOption, e.message
84
+ end
85
+
86
+ # Define 'delivery_options' and 'client' setter methods. These methods are
87
+ # generating a hash where the key is the 'delivery_system'. This let us to
88
+ # set/use more than one API.
89
+ %w[delivery_options delivery_settings client].each do |method|
90
+ define_method "#{method}=" do |value|
91
+ variable = instance_variable_get("@#{method}")
92
+ variable = instance_variable_set("@#{method}", {}) if variable.nil?
93
+ variable[@delivery_system] = value
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MailPlugger
4
+ class DeliveryMethod
5
+ include MailHelper
6
+
7
+ # Initialize delivery method attributes. If we are using MailPlugger.plug_in
8
+ # method, then these attributes can be nil, if not then we should set these
9
+ # attributes.
10
+ #
11
+ # @param [Hash] options with the credentials
12
+ def initialize(options = {})
13
+ @delivery_options = options[:delivery_options] ||
14
+ MailPlugger.delivery_options
15
+
16
+ @client = options[:client] || MailPlugger.client
17
+
18
+ @default_delivery_system = options[:default_delivery_system] ||
19
+ default_delivery_system_get
20
+
21
+ @delivery_settings = options[:delivery_settings] ||
22
+ MailPlugger.delivery_settings
23
+
24
+ @message = nil
25
+ end
26
+
27
+ # Send message with the given client if the message parameter is a
28
+ # Mail::Message object. Before doing that extract those information from the
29
+ # Mail::Message object which was provided in the 'delivery_options'. After
30
+ # that it generates a hash with these data and sends the message with the
31
+ # provided client class which has a 'deliver' method.
32
+ #
33
+ # @param [Mail::Message] message what we would like to send
34
+ def deliver!(message)
35
+ unless message.is_a?(Mail::Message)
36
+ raise Error::WrongParameter,
37
+ 'The given parameter is not a Mail::Message'
38
+ end
39
+
40
+ @message = message
41
+
42
+ client.new(delivery_data).deliver
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MailPlugger
4
+ class Error < StandardError
5
+ # Specific error class for errors if client is not given or has a wrong type
6
+ class WrongApiClient < Error; end
7
+
8
+ # Specific error class for errors if delivery options is not given or
9
+ # has a wrong type
10
+ class WrongDeliveryOptions < Error; end
11
+
12
+ # Specific error class for errors if delivery settings has a wrong type
13
+ class WrongDeliverySettings < Error; end
14
+
15
+ # Specific error class for errors if delivery system is not given
16
+ class WrongDeliverySystem < Error; end
17
+
18
+ # Specific error class for errors if parameter is not given
19
+ class WrongParameter < Error; end
20
+
21
+ # Specific error class for errors if tries to add undelclared option
22
+ # in plug_in block
23
+ class WrongPlugInOption < Error; end
24
+ end
25
+ end
@@ -0,0 +1,185 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+
5
+ module MailPlugger
6
+ module MailHelper
7
+ # Check the version of a gem.
8
+ #
9
+ # @param [String] gem_name the name of the gem
10
+ # @param [String] version the satisfied version of the gem
11
+ #
12
+ # @return [Boolean] true/false
13
+ def check_version_of(gem_name, version)
14
+ requirement = Gem::Requirement.new(version)
15
+ current_version = Gem.loaded_specs[gem_name].version
16
+
17
+ requirement.satisfied_by?(current_version)
18
+ end
19
+
20
+ # Extract 'client'. If it's a hash then it'll return the right
21
+ # client belongs to the delivery system. If it's not a hash it'll return
22
+ # the given value. But if the value doesn't a class it'll raise an error.
23
+ #
24
+ # @return [Class] the defined API class
25
+ def client
26
+ api_client = option_value_from(@client)
27
+
28
+ unless api_client.is_a?(Class)
29
+ raise Error::WrongApiClient, '"client" does not a Class'
30
+ end
31
+ unless api_client.method_defined?(:deliver)
32
+ raise Error::WrongApiClient, '"client" does not have "deliver" method'
33
+ end
34
+
35
+ api_client
36
+ end
37
+
38
+ # Collects data from Mail::Message object.
39
+ #
40
+ # @return [Hash] the data which was defined in 'delivery_options'
41
+ def delivery_data
42
+ data = {}
43
+
44
+ delivery_options.each do |option|
45
+ data[option] =
46
+ case option
47
+ when :from, :to, :cc, :bcc, :subject
48
+ @message.public_send(option)
49
+ when :attachments
50
+ extract_attachments
51
+ when :body, :html_part, :text_part
52
+ @message.public_send(option)&.decoded
53
+ else
54
+ message_field_value_from(@message[option.to_s])
55
+ end
56
+ end
57
+
58
+ data
59
+ end
60
+
61
+ # Tries to set up a default delivery system, if the 'delivery_system'
62
+ # wasn't defined in the Mail::Message object and 'delivery_options' and/or
63
+ # 'client' is a hash. Which means the MailPlugger.plugin method was used,
64
+ # probably.
65
+ #
66
+ # @return [Stirng] the first key of the 'delivery_options' or 'client'
67
+ def default_delivery_system_get
68
+ if @delivery_options.is_a?(Hash)
69
+ @delivery_options
70
+ elsif @client.is_a?(Hash)
71
+ @client
72
+ end&.keys&.first
73
+ end
74
+
75
+ # Extract 'delivery_options'. If it's a hash then it'll return the right
76
+ # options belongs to the delivery system. If it's not a hash it'll return
77
+ # the given value. But if the value doesn't an array it'll raise an error.
78
+ #
79
+ # @return [Array] the options it'll collect from the Mail::Message object
80
+ def delivery_options
81
+ options = option_value_from(@delivery_options)
82
+
83
+ unless options.is_a?(Array)
84
+ raise Error::WrongDeliveryOptions,
85
+ '"delivery_options" does not an Array'
86
+ end
87
+
88
+ options
89
+ end
90
+
91
+ # Extract 'delivery_system' from the Mail::Message object or if it's not
92
+ # defined then use the default one. If it's still nil and one of the
93
+ # 'delivery_options' or 'client' is a hash then raise error.
94
+ #
95
+ # @return [String] with the name of the delivery system
96
+ def delivery_system
97
+ @delivery_system ||=
98
+ (@message && message_field_value_from(@message['delivery_system'])) ||
99
+ @default_delivery_system
100
+
101
+ if @delivery_system.nil? &&
102
+ (@delivery_options.is_a?(Hash) || @client.is_a?(Hash))
103
+ raise Error::WrongDeliverySystem,
104
+ '"delivery_system" was not defined as a Mail::Message parameter'
105
+ end
106
+
107
+ @delivery_system
108
+ end
109
+
110
+ # Extract attachments.
111
+ #
112
+ # @return [Array] with extracted attachment hashes
113
+ def extract_attachments
114
+ @message.attachments&.map do |attachment|
115
+ hash =
116
+ if attachment.inline?
117
+ { cid: attachment.cid }
118
+ else
119
+ { filename: attachment.filename }
120
+ end
121
+
122
+ hash.merge(
123
+ type: attachment.mime_type,
124
+ content: Base64.encode64(attachment.decoded)
125
+ )
126
+ end
127
+ end
128
+
129
+ # How to Extract the (uparsed) value of the mail message fields.
130
+ #
131
+ # @return [String] version dependent method call
132
+ def mail_field_value
133
+ @mail_field_value ||=
134
+ if check_version_of('mail', '> 2.7.0')
135
+ %w[unparsed_value]
136
+ elsif check_version_of('mail', '= 2.7.0')
137
+ %w[instance_variable_get @unparsed_value]
138
+ elsif check_version_of('mail', '< 2.7.0')
139
+ %w[instance_variable_get @value]
140
+ end
141
+ end
142
+
143
+ # Extract the (unparsed) value of the mail message fields.
144
+ #
145
+ # @param [Mail::Field] message_field
146
+ #
147
+ # @return [String/Boolean/Hash] with the field (unparsed) value
148
+ def message_field_value_from(message_field)
149
+ return if message_field.nil?
150
+
151
+ message_field.public_send(*mail_field_value)
152
+ end
153
+
154
+ # Extract the value from the given options.
155
+ #
156
+ # @param [Hash/Array/Class] option
157
+ #
158
+ # @return [Hash/Array/Class] with the option value
159
+ def option_value_from(option)
160
+ if option.is_a?(Hash) && option[delivery_system]
161
+ option[delivery_system]
162
+ else
163
+ option
164
+ end
165
+ end
166
+
167
+ # Extract 'settings'. If it's a hash then it'll return the right
168
+ # settings belongs to the delivery system. If it's not a hash it'll return
169
+ # the given value. But if the value doesn't a hash it'll raise an error.
170
+ #
171
+ # @return [Hash] settings for Mail delivery_method
172
+ def settings
173
+ @settings ||= option_value_from(@delivery_settings)
174
+
175
+ return {} if @settings.nil?
176
+
177
+ unless @settings.is_a?(Hash)
178
+ raise Error::WrongDeliverySettings,
179
+ '"delivery_settings" does not a Hash'
180
+ end
181
+
182
+ @settings
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MailPlugger
4
+ class Railtie < Rails::Railtie
5
+ initializer 'mail_plugger.add_delivery_method' do
6
+ ActiveSupport.on_load :action_mailer do
7
+ ActionMailer::Base.add_delivery_method(
8
+ :mail_plugger,
9
+ MailPlugger::DeliveryMethod
10
+ )
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MailPlugger
4
+ VERSION = '1.0.0.beta1'
5
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/mail_plugger/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'mail_plugger'
7
+ spec.version = MailPlugger::VERSION
8
+ spec.authors = ['Norbert Szivós']
9
+ spec.email = ['sysqa@yahoo.com']
10
+
11
+ spec.summary = 'Plug in the required mailer API(s) with MailPlugger.'
12
+ spec.description = 'Delivery Method to send emails via the defined ' \
13
+ 'API(s), e.g. for Rails ActionMailer.'
14
+ spec.homepage = 'https://github.com/norbertszivos/mail_plugger'
15
+ spec.license = 'MIT'
16
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
17
+
18
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
19
+
20
+ spec.metadata['homepage_uri'] = spec.homepage
21
+ spec.metadata['source_code_uri'] =
22
+ 'https://github.com/norbertszivos/mail_plugger'
23
+ spec.metadata['changelog_uri'] =
24
+ 'https://github.com/norbertszivos/mail_plugger/CHANGELOG.md'
25
+
26
+ # Specify which files should be added to the gem when it is released.
27
+ # The `git ls-files -z` loads the files in the RubyGem
28
+ # that have been added into git.
29
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
30
+ `git ls-files -z`.split("\x0").reject do |f|
31
+ f.match(%r{^(test|spec|features)/})
32
+ end
33
+ end
34
+ spec.bindir = 'exe'
35
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
36
+ spec.require_paths = ['lib']
37
+
38
+ spec.add_dependency 'mail', '~> 2.5'
39
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mail_plugger
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.beta1
5
+ platform: ruby
6
+ authors:
7
+ - Norbert Szivós
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-01-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mail
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.5'
27
+ description: Delivery Method to send emails via the defined API(s), e.g. for Rails
28
+ ActionMailer.
29
+ email:
30
+ - sysqa@yahoo.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".github/ISSUE_TEMPLATE/bug_report.md"
36
+ - ".github/ISSUE_TEMPLATE/feature_request.md"
37
+ - ".gitignore"
38
+ - ".rspec"
39
+ - ".rubocop.yml"
40
+ - ".travis.yml"
41
+ - Appraisals
42
+ - CHANGELOG.md
43
+ - CODE_OF_CONDUCT.md
44
+ - CONTRIBUTING.md
45
+ - Gemfile
46
+ - Gemfile.lock
47
+ - LICENSE.txt
48
+ - README.md
49
+ - Rakefile
50
+ - bin/console
51
+ - bin/setup
52
+ - docs/usage_in_ruby_on_rails.md
53
+ - docs/usage_in_script_or_console.md
54
+ - gemfiles/.bundle/config
55
+ - gemfiles/mail_2.6.gemfile
56
+ - gemfiles/mail_2.6.gemfile.lock
57
+ - gemfiles/mail_2.7.0.gemfile
58
+ - gemfiles/mail_2.7.0.gemfile.lock
59
+ - gemfiles/mail_2.7.gemfile
60
+ - gemfiles/mail_2.7.gemfile.lock
61
+ - images/mail_plugger.png
62
+ - lib/mail_plugger.rb
63
+ - lib/mail_plugger/delivery_method.rb
64
+ - lib/mail_plugger/error.rb
65
+ - lib/mail_plugger/mail_helper.rb
66
+ - lib/mail_plugger/railtie.rb
67
+ - lib/mail_plugger/version.rb
68
+ - mail_plugger.gemspec
69
+ homepage: https://github.com/norbertszivos/mail_plugger
70
+ licenses:
71
+ - MIT
72
+ metadata:
73
+ homepage_uri: https://github.com/norbertszivos/mail_plugger
74
+ source_code_uri: https://github.com/norbertszivos/mail_plugger
75
+ changelog_uri: https://github.com/norbertszivos/mail_plugger/CHANGELOG.md
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 2.5.0
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">"
88
+ - !ruby/object:Gem::Version
89
+ version: 1.3.1
90
+ requirements: []
91
+ rubygems_version: 3.2.3
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: Plug in the required mailer API(s) with MailPlugger.
95
+ test_files: []