sendgrid_notification 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +92 -0
  4. data/Rakefile +36 -0
  5. data/app/assets/config/sendgrid_notification_manifest.js +2 -0
  6. data/app/assets/javascripts/sendgrid_notification/application.js +13 -0
  7. data/app/assets/stylesheets/sendgrid_notification/application.css +15 -0
  8. data/app/controllers/sendgrid_notification/application_controller.rb +5 -0
  9. data/app/helpers/sendgrid_notification/application_helper.rb +4 -0
  10. data/app/jobs/sendgrid_notification/application_job.rb +4 -0
  11. data/app/jobs/sendgrid_notification/sendmail_job.rb +11 -0
  12. data/app/mailers/sendgrid_notification/application_mailer.rb +6 -0
  13. data/app/models/sendgrid_notification/application_record.rb +5 -0
  14. data/app/models/sendgrid_notification/mail_history.rb +15 -0
  15. data/app/models/sendgrid_notification/mail_recordable.rb +17 -0
  16. data/app/models/sendgrid_notification/notification_mail.rb +39 -0
  17. data/app/models/sendgrid_notification/null_mailer.rb +29 -0
  18. data/app/models/sendgrid_notification/sendgrid_client.rb +88 -0
  19. data/app/models/sendgrid_notification/sendgrid_mailer.rb +45 -0
  20. data/app/models/sendgrid_notification/sendgrid_status.rb +89 -0
  21. data/app/models/sendgrid_notification/sendgrid_status_update_history.rb +16 -0
  22. data/app/models/sendgrid_notification/template_parameters_validator.rb +12 -0
  23. data/app/views/layouts/sendgrid_notification/application.html.erb +14 -0
  24. data/config/routes.rb +2 -0
  25. data/db/migrate/20170208085706_create_notification_mails.rb +13 -0
  26. data/db/migrate/20170208113843_create_mail_histories.rb +13 -0
  27. data/db/migrate/20170217072256_create_sendgrid_status_update_histories.rb +12 -0
  28. data/lib/sendgrid_notification/engine.rb +19 -0
  29. data/lib/sendgrid_notification/version.rb +3 -0
  30. data/lib/sendgrid_notification.rb +4 -0
  31. data/lib/tasks/sendgrid_notification_tasks.rake +56 -0
  32. metadata +186 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 90775898ca7fc2946047128eedcdddce10254fdf
4
+ data.tar.gz: f1ac7c958212d54a465c8f22af4cda0dcd587e1f
5
+ SHA512:
6
+ metadata.gz: 900f013823a5951052e7c113080d84b03a7381ddf61362fff59227543631c2a222e4e49d2db9f91bb21798368cf427679d5c15240284319cbd962d79b647ef29
7
+ data.tar.gz: 9b91afb7880024fc55f2edf5cdf65d0520441a5cba56af5733507b7de3b3e8c3673b58d77fd600a42bc3af6c503d0a0cf37c4a684d8c8157dbe64a6cc9694a30
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2017 HORII Keima
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.
data/README.md ADDED
@@ -0,0 +1,92 @@
1
+ # SendgridNotification
2
+
3
+ SendgridNotification is engine of Ruby on Rails, and
4
+ notification mail (e.g. account registration, logging in by new devise,
5
+ reminder, etc...) sender and utility, using SendGrid API.
6
+
7
+ This provides mail utility models, migrations, and rake tasks.
8
+
9
+ ## Installation / Usage
10
+
11
+ First, add sendgird_notification in Gemfile
12
+
13
+ ```ruby
14
+ gem 'sendgrid_notification'
15
+ ```
16
+
17
+ ```sh
18
+ bundle install
19
+ ```
20
+
21
+ Then, generate migration files and migrate
22
+
23
+ ```sh
24
+ bin/rails sendgrid_notification_engine:install:migrations
25
+ bin/rails db:migrate
26
+ ```
27
+
28
+ Generate and edit controllers for NotificationMail CRUD
29
+
30
+ ```
31
+ ...
32
+ ```
33
+
34
+ Create NotificationMail record. key = 'example'
35
+
36
+
37
+ ```
38
+ ...
39
+ ```
40
+
41
+ And send the mail
42
+
43
+ ```
44
+ ...
45
+ ```
46
+
47
+ Oops. It lacks SendGrid API configuration. Get API key from sendgrid.com and set it ENV['SENDGRID_API_KEY']
48
+
49
+
50
+ ```
51
+ ...
52
+ ```
53
+
54
+ ### Make subclasses for each notification_mail key
55
+
56
+ ```
57
+ ...
58
+ ```
59
+
60
+ ### Validate mail template has right parameter name
61
+
62
+ ```
63
+ ...
64
+ ```
65
+
66
+ ## Configuration
67
+
68
+ | Name | Description | Default Value |
69
+ |------|-------------|---------------|
70
+ | config.sendgrid_notification.api_key | SendGrid API Key | `ENV['SENDGRID_API_KEY']` |
71
+ | config.sendgrid_notification.mail_from | FROM address of notification mail | `ENV['SENDGRID_MAIL_FROM']` |
72
+ | config.sendgrid_notification.mail_from_name | FROM name of notification mail | `ENV['SENDGRID_MAIL_FROM_NAME']` |
73
+ | config.sendgrid_notification.mailer | Mailer class name (by string). usually no need to change | `"SendgridNotification::SendgridMailer"` |
74
+
75
+ ## Rake tasks
76
+
77
+ | Task | Description | ENV/Parameter |
78
+ |------|-------------|----------------|
79
+ | sendgrid_notification:send | Send mail | TO=[recipient email address] KEY=[mail type key] ... and mail parameters |
80
+ | sendgrid_notification:status:autoupdate | Update status from previous autoupdate task | |
81
+ | sendgrid_notification:status:retrieve | Only retrieve suppression statuses in start..end | start=[datetime] end=[datetime] |
82
+ | sendgrid_notification:status:update | Retrieve suppression status and update record | start=[datetime] end=[datetime] |
83
+ | sendgrid_notification:testmail:init | Create notification_mails test record. default key = "_test" |
84
+ | sendgrid_notification:testmail:send | Send testmail | TO=[recipient email address] [body=body] |
85
+
86
+ ## Contributing
87
+
88
+ Contribution directions go here.
89
+
90
+ ## License
91
+
92
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,36 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'SendgridNotification'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+ load 'rails/tasks/statistics.rake'
22
+
23
+
24
+
25
+ require 'bundler/gem_tasks'
26
+
27
+ require 'rake/testtask'
28
+
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'test'
31
+ t.pattern = 'test/**/*_test.rb'
32
+ t.verbose = false
33
+ end
34
+
35
+
36
+ task default: :test
@@ -0,0 +1,2 @@
1
+ //= link_directory ../javascripts/sendgrid_notification .js
2
+ //= link_directory ../stylesheets/sendgrid_notification .css
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file. JavaScript code in this file should be added after the last require_* statement.
9
+ //
10
+ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,5 @@
1
+ module SendgridNotification
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery with: :exception
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module SendgridNotification
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module SendgridNotification
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,11 @@
1
+ module SendgridNotification
2
+ class SendmailJob < ActiveJob::Base
3
+ queue_as :sendmail
4
+
5
+ MailerClass = Rails.application.config.sendgrid_notification.mailer.constantize
6
+
7
+ def perform(to, notification_mail, params)
8
+ MailerClass.new.sendmail(to, notification_mail, params)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ module SendgridNotification
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module SendgridNotification
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ module SendgridNotification
2
+ class MailHistory < ActiveRecord::Base
3
+ belongs_to :notification_mail, primary_key: :key, foreign_key: :key, required: false
4
+
5
+ with_options presence: true do
6
+ validates :key
7
+ validates :to
8
+ validates :sent_at
9
+ end
10
+
11
+ def error?
12
+ error_type?
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ # prepend me
2
+ module SendgridNotification
3
+ module MailRecordable
4
+ def sendmail(to, notification_mail, params = {})
5
+ result = super
6
+
7
+ m = MailHistory.create(
8
+ key: notification_mail.key,
9
+ to: to,
10
+ sent_at: Time.now,
11
+ )
12
+ Rails.logger.error m.errors.full_messages if m.invalid? # and ignore
13
+
14
+ result
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,39 @@
1
+ module SendgridNotification
2
+ class NotificationMail < ActiveRecord::Base
3
+
4
+ with_options presence: true do
5
+ validates :key, uniqueness: true
6
+ validates :subject
7
+ validates :content
8
+ end
9
+
10
+ class_attribute :variable_regexp
11
+
12
+ VARIABLE_REGEXP_DEFAULT = /\{\{\s*(\w+)\s*\}\}/
13
+ self.variable_regexp = VARIABLE_REGEXP_DEFAULT
14
+
15
+
16
+ def sendmail_later(to, params = {})
17
+ SendmailJob.perform_later(to, self, params)
18
+ end
19
+
20
+ alias_method :sendmail, :sendmail_later
21
+
22
+ def sendmail_now(to, params = {})
23
+ SendmailJob.perform_now(to, self, params)
24
+ end
25
+
26
+ def apply(params)
27
+ unresolved = []
28
+ body = content.gsub(variable_regexp) { |_|
29
+ key = $1
30
+ params[key] || params[key.to_sym] || unresolved.push(key)
31
+ }
32
+ if unresolved.present?
33
+ errors.add(:content, :unresolved_template_parameters, variables: unresolved.join(","))
34
+ end
35
+ body
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,29 @@
1
+ require 'sendgrid-ruby'
2
+
3
+ module SendgridNotification
4
+ class NullMailer
5
+ prepend MailRecordable
6
+
7
+ Result = Struct.new(:from, :to, :subject, :body, :sent_at)
8
+
9
+ @@results = []
10
+ cattr_reader :results
11
+
12
+ def initialize
13
+ @from = Rails.application.config.sendgrid_notification.mail_from
14
+ end
15
+
16
+ def sendmail(to, notification_mail, params = {})
17
+ body = notification_mail.apply(params)
18
+ results << Result.new(@from, to, notification_mail.subject, body, Time.now)
19
+ end
20
+
21
+ def last_result
22
+ results.last
23
+ end
24
+
25
+ def last_result_success?
26
+ results.present?
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,88 @@
1
+ require 'sendgrid-ruby'
2
+
3
+ # monkey patch
4
+ class SendGrid::Response
5
+ # about status code, see https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/errors.html
6
+ def success?
7
+ status_code && status_code.to_i < 300
8
+ end
9
+ end
10
+
11
+ module SendgridNotification
12
+ class SendgridClient
13
+ class Error < RuntimeError; end
14
+
15
+ class Response < SendGrid::Response
16
+ attr_reader :raw
17
+
18
+ def initialize(send_grid_response) # SendGrid::Response, has status_code, body, headers
19
+ @raw = send_grid_response
20
+ end
21
+
22
+ def status_code
23
+ raw.try(:status_code).try(:to_i)
24
+ end
25
+
26
+ def success?
27
+ status_code && status_code < 300
28
+ end
29
+
30
+ def body
31
+ raw.try(:body) ? JSON.parse(raw.body) : ''
32
+ end
33
+
34
+ delegate :headers, to: :raw
35
+ end
36
+
37
+ attr_reader :api_key, :api, :last_response
38
+
39
+ delegate :client, to: :api
40
+
41
+ def initialize
42
+ @api_key = Rails.application.config.sendgrid_notification.api_key
43
+ if api_key.blank?
44
+ raise Error, "no sendgrid api_key. set config.sendgrid_notification.api_key or " \
45
+ "SENDGRID_API_KEY environment variable."
46
+ end
47
+ @api = SendGrid::API.new(api_key: api_key)
48
+ @last_response = nil
49
+ end
50
+
51
+ # TODO: status_code が 500 系およびタイムアウトのときにリトライできるようにする
52
+ # POST /mail/send
53
+ def mail_send(from:, from_name:, to:, subject:, body:)
54
+ mail = build_mail(from, from_name, to, subject, body)
55
+ res = client.mail._('send').post(request_body: mail.to_json)
56
+ @last_response = Response.new(res)
57
+ end
58
+
59
+ SUPPRESSION_TYPES = %w(invalid_emails bounces blocks).freeze
60
+
61
+ # GET /suppression/#{type}/
62
+ def suppression_get(suppression_type, start_time:, end_time:, limit: 100, offset: 0)
63
+ unless SUPPRESSION_TYPES.include?(suppression_type.to_s)
64
+ # 警告のみ
65
+ Rails.logger.error("Unknown suppresssion type '#{suppression_type}'")
66
+ end
67
+
68
+ params = {
69
+ start_time: start_time.to_i,
70
+ end_time: end_time.to_i,
71
+ limit: limit,
72
+ offset: offset,
73
+ }
74
+ res = client.suppression._(suppression_type).get(query_params: params)
75
+ @last_response = Response.new(res)
76
+ end
77
+
78
+ private
79
+
80
+ def build_mail(mail_from, mail_from_name, mail_to, subject, body)
81
+ from = SendGrid::Email.new(email: mail_from, name: mail_from_name)
82
+ to = SendGrid::Email.new(email: mail_to)
83
+ content = SendGrid::Content.new(type: 'text/plain', value: body)
84
+
85
+ SendGrid::Mail.new(from, subject, to, content)
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,45 @@
1
+ require 'sendgrid-ruby'
2
+
3
+ module SendgridNotification
4
+ class SendgridMailer
5
+ prepend MailRecordable
6
+
7
+ class Error < StandardError; end
8
+
9
+ def initialize
10
+ @from = Rails.application.config.sendgrid_notification.mail_from
11
+ @from_name = Rails.application.config.sendgrid_notification.mail_from_name
12
+ end
13
+
14
+ def sendmail(to, notification_mail, params = {})
15
+ body = notification_mail.apply(params)
16
+ _sendmail(to, notification_mail, body)
17
+ end
18
+
19
+ def last_result
20
+ # SendGrid::Response class
21
+ # https://github.com/sendgrid/ruby-http-client/blob/master/lib/ruby_http_client.rb
22
+ sendgrid_client.last_response
23
+ end
24
+
25
+ def last_result_success?
26
+ sendgrid_client.last_response.try!(:success?)
27
+ end
28
+
29
+ private
30
+
31
+ def sendgrid_client
32
+ @sendgrid_client ||= SendgridClient.new
33
+ end
34
+
35
+ def _sendmail(to, notification_mail, body)
36
+ sendgrid_client.mail_send(
37
+ from: @from,
38
+ from_name: @from_name,
39
+ to: to,
40
+ subject: notification_mail.subject,
41
+ body: body
42
+ )
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,89 @@
1
+ require 'sendgrid-ruby'
2
+
3
+ module SendgridNotification
4
+ class SendgridStatus
5
+ class RetrieveError < ::StandardError; end
6
+
7
+ # mapped to sendgrid api result
8
+ # e.g. https://sendgrid.com/docs/API_Reference/Web_API_v3/blocks.html
9
+ # ( なお invalid_emails には status がない。そもそも送っていないから。 )
10
+ Suppression = Struct.new(:type, :created, :email, :reason, :status) do
11
+ def self.build(type, hash)
12
+ new(type, *hash.values_at('created', 'email', 'reason', 'status'))
13
+ end
14
+
15
+ def to_s
16
+ to_h.to_json
17
+ end
18
+ end
19
+
20
+ def self.auto_update
21
+ last = SendgridStatusUpdateHistory.last
22
+ start_time = last ? last.end_time : 1.hour.ago.to_i
23
+ end_time = Time.now.to_i
24
+
25
+ suppressions = update(start_time, end_time)
26
+
27
+ SendgridStatusUpdateHistory.create!(
28
+ start_time: start_time,
29
+ end_time: end_time,
30
+ count: suppressions.size,
31
+ body: suppressions.map(&:to_s).join("\n")
32
+ )
33
+ end
34
+
35
+ # TODO: 前回の保存日時からの内容を記録
36
+ def self.update(start_time = 1.hour.ago, end_time = Time.now)
37
+ suppressions = retrieve_all(start_time, end_time)
38
+ suppressions.each do |s|
39
+ update_mail_history(s.email, s.created, s.type, s.reason)
40
+ end
41
+ suppressions
42
+ end
43
+
44
+ def self.retrieve_all(start_time, end_time)
45
+ SendgridClient::SUPPRESSION_TYPES.each_with_object([]) do |type, suppressions|
46
+ result = retrieve(type, start_time, end_time)
47
+ suppressions.concat result
48
+ end
49
+ end
50
+
51
+ # type is one of SendgridClient::SUPPRESSION_TYPES
52
+ # {start,end}_time is Time or Integer
53
+ def self.retrieve(type, start_time, end_time, limit = 100)
54
+ _client = client
55
+ offset = 0
56
+ suppressions = []
57
+ begin
58
+ res = _client.suppression_get(type,
59
+ start_time: start_time.to_i, end_time: end_time.to_i,
60
+ limit: limit, offset: offset)
61
+ # FIXME: if timeout?
62
+ if res.success?
63
+ # res.body is type of [{}]
64
+ results = res.body.map { |h| Suppression.build(type.to_s, h) }
65
+ suppressions.concat results
66
+ else
67
+ # Rails.logger.warn "sendgrid returns status code #{res.status_code}. (#{type}, #{start_time}, #{end_time})"
68
+ raise RetrieveError, "sendgrid returns status code #{res.status_code}. (#{type}, #{start_time}, #{end_time})"
69
+ end
70
+ offset += limit
71
+ end while results.size == limit
72
+ suppressions
73
+ end
74
+
75
+ def self.client
76
+ SendgridClient.new
77
+ end
78
+
79
+ # status_timestamp allows Integer unix timestamp
80
+ def self.update_mail_history(mailto, status_timestamp, error_type, error_reason, relation = MailHistory.all)
81
+ target = relation.order(:sent_at).where(to: mailto).where('sent_at <= ?', Time.at(status_timestamp)).first
82
+ if target
83
+ target.update!(error_type: error_type, error_reason: error_reason)
84
+ else
85
+ Rails.logger.warn("SendgridStatus::Updater#update: Fail to find history; mailto: #{mailto}, created: #{status_timestamp}, error_type: #{error_type}, error_reason: #{error_reason}")
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,16 @@
1
+ module SendgridNotification
2
+ class SendgridStatusUpdateHistory < ActiveRecord::Base
3
+ with_options numericality: { only_integer: true } do
4
+ validates :start_time
5
+ validates :end_time
6
+ end
7
+
8
+ def start_time_in_time_zone
9
+ Time.zone.at(start_time)
10
+ end
11
+
12
+ def end_time_in_time_zone
13
+ Time.zone.at(end_time)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ module SendgridNotification
2
+ class TemplateParametersValidator < ActiveModel::Validator
3
+ def initialize(options)
4
+ @parameter_keys ||= Array(options[:parameters]) || []
5
+ end
6
+
7
+ def validate(record)
8
+ params = @parameter_keys.map{|k| [k, k] }.to_h
9
+ record.apply(params)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Sendgrid notification</title>
5
+ <%= stylesheet_link_tag "sendgrid_notification/application", media: "all" %>
6
+ <%= javascript_include_tag "sendgrid_notification/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ SendgridNotification::Engine.routes.draw do
2
+ end
@@ -0,0 +1,13 @@
1
+ class CreateNotificationMails < ActiveRecord::Migration[5.1]
2
+ def change
3
+ create_table :notification_mails do |t|
4
+ t.string :key, null: false
5
+ t.string :subject, null: false
6
+ t.text :content, null: false
7
+
8
+ t.timestamps null: false
9
+ end
10
+
11
+ add_index :notification_mails, :key, unique: true
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ class CreateMailHistories < ActiveRecord::Migration[5.1]
2
+ def change
3
+ create_table :mail_histories do |t|
4
+ t.string :key, null: false
5
+ t.string :to, null: false
6
+ t.timestamp :sent_at, null: false
7
+ t.string :error_type
8
+ t.text :error_reason
9
+
10
+ t.timestamps null: false
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ class CreateSendgridStatusUpdateHistories < ActiveRecord::Migration[5.1]
2
+ def change
3
+ create_table :sendgrid_status_update_histories do |t|
4
+ t.integer :start_time, null: false
5
+ t.integer :end_time, null: false
6
+ t.integer :count
7
+ t.text :body
8
+
9
+ t.timestamps null: false
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,19 @@
1
+ module SendgridNotification
2
+ class Engine < ::Rails::Engine
3
+ config.sendgrid_notification = ActiveSupport::OrderedOptions.new
4
+
5
+ initializer "sendgrid_notification.mailer" do |app|
6
+ app.config.sendgrid_notification.mailer ||= "SendgridNotification::SendgridMailer"
7
+ # if test or dev, use NullMailer instead
8
+ end
9
+
10
+ initializer "sendgrid_notification.api_key" do |app|
11
+ app.config.sendgrid_notification.api_key ||= ENV['SENDGRID_API_KEY']
12
+ end
13
+
14
+ initializer "sendgrid_notification.mail_from" do |app|
15
+ app.config.sendgrid_notification.mail_from ||= ENV['SENDGRID_MAIL_FROM']
16
+ app.config.sendgrid_notification.mail_from_name ||= ENV['SENDGRID_MAIL_FROM_NAME']
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module SendgridNotification
2
+ VERSION = "0.1.0".freeze
3
+ end
@@ -0,0 +1,4 @@
1
+ require "sendgrid_notification/engine"
2
+
3
+ module SendgridNotification
4
+ end
@@ -0,0 +1,56 @@
1
+ namespace :sendgrid_notification do
2
+ namespace :testmail do
3
+ desc 'Create notification_mails test record, KEY = "_test"'
4
+ task init: :environment do
5
+ key = ENV['KEY'] || '_test'
6
+ SendgridNotification::NotificationMail.find_or_create_by!(key: key) do |m|
7
+ m.subject = 'Test mail subject'
8
+ m.content = <<-EOD
9
+ This is test mail.
10
+ {{ body }}
11
+ EOD
12
+ end
13
+ end
14
+
15
+ desc 'Send testmail (TO=address [body=body])'
16
+ task send: :environment do
17
+ ENV['KEY'] ||= '_test'
18
+ ARGV << 'body=[body parameter expected]' unless ENV['body']
19
+ Rake::Task["sendgrid_notification:send"].invoke
20
+ end
21
+ end
22
+
23
+ desc 'Send mail (TO=address KEY=mail_key and describe parameter...)'
24
+ task send: :environment do
25
+ to = ENV.fetch('TO')
26
+ key = ENV.fetch('KEY')
27
+ params = ARGV.each_with_object({}) do |arg, hash|
28
+ hash[Regexp.last_match(1)] = Regexp.last_match(2) if arg =~ /^(\w+)=(.*)$/m
29
+ end
30
+
31
+ m = SendgridNotification::NotificationMail.find_by!(key: key)
32
+ m.sendmail(to, params)
33
+ end
34
+
35
+ namespace :status do
36
+ desc 'update status (start=datetime end=datetime)'
37
+ task update: :environment do
38
+ start_time = Time.parse ENV.fetch('start')
39
+ end_time = Time.parse ENV.fetch('end')
40
+ SendgridNotification::SendgridStatus.update(start_time, end_time)
41
+ end
42
+
43
+ desc 'update status after previous autoupdate'
44
+ task autoupdate: :environment do
45
+ SendgridNotification::SendgridStatus.auto_update
46
+ end
47
+
48
+ desc 'only retrieve suppression statuses (start=datetime end=datetime)'
49
+ task retrieve: :environment do
50
+ start_time = Time.parse ENV.fetch('start')
51
+ end_time = Time.parse ENV.fetch('end')
52
+ suppressions = SendgridNotification::SendgridStatus.retrieve_all(start_time, end_time)
53
+ puts suppressions
54
+ end
55
+ end
56
+ end
metadata ADDED
@@ -0,0 +1,186 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sendgrid_notification
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - HORII Keima
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-08-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '5.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sendgrid-ruby
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest-power_assert
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: factory_girl_rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: guard-minitest
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: minitest-rg
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: notification mail sender via sendgrid API
126
+ email:
127
+ - holysugar@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - MIT-LICENSE
133
+ - README.md
134
+ - Rakefile
135
+ - app/assets/config/sendgrid_notification_manifest.js
136
+ - app/assets/javascripts/sendgrid_notification/application.js
137
+ - app/assets/stylesheets/sendgrid_notification/application.css
138
+ - app/controllers/sendgrid_notification/application_controller.rb
139
+ - app/helpers/sendgrid_notification/application_helper.rb
140
+ - app/jobs/sendgrid_notification/application_job.rb
141
+ - app/jobs/sendgrid_notification/sendmail_job.rb
142
+ - app/mailers/sendgrid_notification/application_mailer.rb
143
+ - app/models/sendgrid_notification/application_record.rb
144
+ - app/models/sendgrid_notification/mail_history.rb
145
+ - app/models/sendgrid_notification/mail_recordable.rb
146
+ - app/models/sendgrid_notification/notification_mail.rb
147
+ - app/models/sendgrid_notification/null_mailer.rb
148
+ - app/models/sendgrid_notification/sendgrid_client.rb
149
+ - app/models/sendgrid_notification/sendgrid_mailer.rb
150
+ - app/models/sendgrid_notification/sendgrid_status.rb
151
+ - app/models/sendgrid_notification/sendgrid_status_update_history.rb
152
+ - app/models/sendgrid_notification/template_parameters_validator.rb
153
+ - app/views/layouts/sendgrid_notification/application.html.erb
154
+ - config/routes.rb
155
+ - db/migrate/20170208085706_create_notification_mails.rb
156
+ - db/migrate/20170208113843_create_mail_histories.rb
157
+ - db/migrate/20170217072256_create_sendgrid_status_update_histories.rb
158
+ - lib/sendgrid_notification.rb
159
+ - lib/sendgrid_notification/engine.rb
160
+ - lib/sendgrid_notification/version.rb
161
+ - lib/tasks/sendgrid_notification_tasks.rake
162
+ homepage: https://github.com/holysugar/sendgrid_notification
163
+ licenses:
164
+ - MIT
165
+ metadata: {}
166
+ post_install_message:
167
+ rdoc_options: []
168
+ require_paths:
169
+ - lib
170
+ required_ruby_version: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ version: '0'
175
+ required_rubygems_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ requirements: []
181
+ rubyforge_project:
182
+ rubygems_version: 2.6.11
183
+ signing_key:
184
+ specification_version: 4
185
+ summary: notification mail sender via sendgrid API
186
+ test_files: []