mailtime 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c6796e6fba8e145db97279c3bfc86388553a9733
4
+ data.tar.gz: 0f3bf01438f14798f016290245047cf4ace18e17
5
+ SHA512:
6
+ metadata.gz: 728b353305727c26f8f16c24583051f98771efe706722381c1e62e5b09630afdac8d304a63d849ff9851e7775371b047bf072cc60cf653973a51b011181d7066
7
+ data.tar.gz: d0ec9ee59c341e33f48bad171db20753c501441e87456bc9157015a113955ddd2dd3521e7ce7d096b71797f8d061ee55ca89f88471f5d3a27e1f8f6cab3abdd5
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mailtime.gemspec
4
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2009-2016 Plataformatec. http://plataformatec.com.br
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,90 @@
1
+ # Mailtime
2
+
3
+ Make sending mail great again.
4
+
5
+ ## Goal
6
+
7
+ For most projects, you want to know when you mailed a user, and what you mailed to them. Additionally, you don't want to have to do a push every time you want to change something in your mailer.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'mailtime'
15
+ ```
16
+
17
+ Bundle.
18
+
19
+ $ bundle
20
+
21
+ And copy over the initializer and migration:
22
+
23
+ $ rails g mailtime:install
24
+
25
+ Migrate it.
26
+
27
+ $ rake db:migrate
28
+
29
+ ## How it works
30
+
31
+ Mailtime hooks into `ActionMailer#mail`. It injects a some methods in order to extract metadata, such as the mailer class (like `UserMailer`) and the action
32
+ (like `password_reset`). Once it knows what it's working with, it looks to the database for the corresponding `MailTemplate`.
33
+ If it finds the `MailTemplate`, it renders the template against the mail and merges the result with some of the mail's attributes (like `body`).
34
+
35
+ It then logs the mail and sends it away.
36
+
37
+ Mailtime aims to be highly flexible and tries not to dictate your setup. For example, you can render a `MailTemplate`'s contents however you want. Just specify in the initializer what `renderer` you want to use. And because Mailtime simply hooks into `ActionMailer`, it doesn't care how you're delivering mail (via `config.action_mailer.delivery_method`).
38
+
39
+ ## Usage
40
+
41
+ Should "just work", but...
42
+
43
+ You'll want somewhere to view your logs and manage your templates. Basic scaffolding will do just fine.
44
+
45
+ ```Ruby
46
+ def index
47
+ @mail_templates = Mailtime::MailTemplate.all
48
+ end
49
+ ```
50
+
51
+ For `MailTemplate`, you'll want to permit the params `klass`, `action`, `subject`, and `content`
52
+
53
+ Here's an example using `SimpleForm`:
54
+
55
+ ```Ruby
56
+ simple_form_for @mail_template do |f|
57
+ f.input :action, :as => :select, :collection => MailTemplate.mail_actions, :onchange => '$("#mail_template_klass").val($("#mail_template_action option:selected").closest("optgroup").attr("label"));'
58
+ f.input :klass, :as => :hidden
59
+ f.input :subject
60
+ f.input :content, :as => :text
61
+ f.submit
62
+ end
63
+ ```
64
+
65
+ `MailTemplate.mail_actions` is an array of mailer classes and their public instance methods, e.g. `['UserMailer' => ['password_reset_email']]`
66
+
67
+ ## Todo
68
+
69
+ * Better loading of mailers
70
+ * Allow config to specify the user class
71
+ * Fallbacks
72
+ * Import existing mailers
73
+ * Layouts
74
+ * Tests
75
+ * BCC, CC
76
+ * Configure overrides for subject
77
+ * Custom user finder
78
+
79
+ ## Maybe todo
80
+
81
+ * WYSIWIG?
82
+ * Sync?
83
+ * Versioning for templates?
84
+ * Specify multiple formats?
85
+ * A/B testing?
86
+
87
+ ## Contributing
88
+
89
+ Bug reports and pull requests are welcome on GitHub at https://github.com/joshmn/mailtime
90
+
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'bundler/gem_tasks'
2
+ task :default => :spec
3
+
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << 'test'
8
+ t.pattern = 'test/*_test.rb'
9
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "mailtime"
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
data/bin/setup ADDED
@@ -0,0 +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
@@ -0,0 +1,11 @@
1
+ Description:
2
+ Copies migrations and installs an initializer
3
+
4
+ Example:
5
+ rails generate mailtime:install
6
+
7
+ This will create:
8
+ config/initializers/mailtime.rb
9
+
10
+ and add a migration of:
11
+ 1_active_admin_mail_migration.rb
@@ -0,0 +1,18 @@
1
+ module Mailtime
2
+ module Generators
3
+ class InstallGenerator < ::Rails::Generators::Base
4
+
5
+ source_root File.expand_path("../templates", __FILE__)
6
+ desc "Installs an initializer and copies over a migration"
7
+
8
+ def copy_initializer_file
9
+ copy_file "default_initializer.rb", "config/initializers/mailtime.rb"
10
+ end
11
+
12
+ def copy_migration_file
13
+ copy_file "db/migrate/1_mailtime_migration.rb", "db/migrate/1_mailtime_migration.rb"
14
+ end
15
+ end
16
+ end
17
+
18
+ end
@@ -0,0 +1,30 @@
1
+ class MailtimeMigration < ActiveRecord::Migration
2
+ def change
3
+ create_table :mailtime_mail_templates do |t|
4
+ t.string :klass
5
+ t.string :action
6
+ t.text :content
7
+ t.text :subject
8
+
9
+ t.timestamps null: false
10
+ end
11
+ add_index :mailtime_mail_templates, :klass
12
+ add_index :mailtime_mail_templates, :action
13
+
14
+ create_table :mailtime_mail_logs do |t|
15
+ t.integer :mailtime_mail_template_id
16
+ t.string :template
17
+ t.string :action
18
+ t.string :klass
19
+ t.integer :user_id
20
+ t.json :headers
21
+
22
+ t.timestamps null: false
23
+ end
24
+ add_index :mailtime_mail_logs, :mailtime_mail_template_id
25
+ add_index :mailtime_mail_logs, :template
26
+ add_index :mailtime_mail_logs, :action
27
+ add_index :mailtime_mail_logs, :klass
28
+ add_index :mailtime_mail_logs, :user_id
29
+ end
30
+ end
@@ -0,0 +1,45 @@
1
+ Mailtime.configure do |config|
2
+
3
+ # == Mailers
4
+ #
5
+ # Unfortunately, Rails doesn't autoload mailers in development
6
+ # If you don't mind restarting your Rails server every time you add a new mailer,
7
+ # you can set this to false.
8
+ config.lazy_load_mailers = false
9
+
10
+ # If you're wondering why Devise's mailers aren't getting picked up (or something similar)
11
+ # you can specify additional mailers below.
12
+ #config.mailers << 'Devise::Mailer'
13
+
14
+ # == Rendering
15
+ #
16
+ # If you do not want to have Mailtime handle the `body` of the mail itself,
17
+ # you should set this to false
18
+ config.render = true
19
+
20
+ # But if you do (and you should), and you want to use your own renderer, specify
21
+ # it here. It's just a PORO that parse the template's (from the database) content
22
+ # and assign the mail's body to it.
23
+ # config.renderer = 'LiquidRenderer'
24
+
25
+ # If for some reason, calling #render on your renderer is not okay, you can specify
26
+ # the method below. (ps. the method should output the contents of the template + mail context)
27
+ # so that it can be assigned to the `body` of the mail
28
+ #config.renderer_method = :render
29
+
30
+ # == Logging
31
+ #
32
+ # Log the mail to the database
33
+ config.log = true
34
+
35
+ # If your user class is not `User`, you can tell Mailtime what it is and for each mail that gets logged
36
+ # to associate it to the instance variable that has this class.
37
+ # todo
38
+ # config.user_class = 'User'
39
+
40
+ # == Fallbacks
41
+ # falls back to ERB if the template doesn't exist in the database
42
+ # raises an error if the template doesn't exist in ERB
43
+ config.fallback_to_erb = false
44
+
45
+ end
@@ -0,0 +1,38 @@
1
+ module Mailtime
2
+ module ActionMailer
3
+ module Metadata
4
+
5
+ def self.included(base)
6
+ base.include AbstractController::Callbacks
7
+ base.after_action :inject_metadata
8
+ end
9
+
10
+ protected
11
+
12
+ def instance_variables_map
13
+ self.instance_variables.select { |variable| !variable.to_s.start_with?("@_") }.each_with_object({}) do |v, h|
14
+ h[v.to_s.gsub('@', '')] = instance_variable_get(v)
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def inject_metadata
21
+ mailer_klass = self.class.to_s
22
+ mailer_action = self.action_name
23
+ action_variables = self.instance_variables_map
24
+
25
+ self.message.instance_variable_set(:@mailer_klass, mailer_klass)
26
+ self.message.instance_variable_set(:@mailer_action, mailer_action)
27
+ self.message.instance_variable_set(:@action_variables, action_variables)
28
+
29
+ self.message.class.send(:attr_reader, :mailer_klass)
30
+ self.message.class.send(:attr_reader, :mailer_action)
31
+ self.message.class.send(:attr_reader, :action_variables)
32
+ end
33
+
34
+ end
35
+ end
36
+ end
37
+
38
+ ::ActionMailer::Base.send(:include, Mailtime::ActionMailer::Metadata)
@@ -0,0 +1,16 @@
1
+ module Mailtime
2
+ class SetupMailtimeMailer
3
+
4
+ class << self
5
+
6
+ def delivering_email(mail)
7
+ processor = Mailtime::Processor.new(mail)
8
+ mail = processor.execute
9
+ mail
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+
16
+ ActionMailer::Base.register_interceptor(Mailtime::SetupMailtimeMailer)
@@ -0,0 +1,9 @@
1
+ require 'mailtime/mail_log_concern'
2
+
3
+ module Mailtime
4
+ class MailLog < ActiveRecord::Base
5
+
6
+ include Mailtime::MailLogConcern
7
+
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'mailtime/mail_template_concern'
2
+
3
+ module Mailtime
4
+ class MailTemplate < ActiveRecord::Base
5
+
6
+ include Mailtime::MailTemplateConcern
7
+
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ module Mailtime
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+
5
+ isolate_namespace Mailtime
6
+
7
+ paths["app/models"] << "lib/mailtime/active_record/models"
8
+
9
+ initializer :append_migrations do |app|
10
+ unless app.root.to_s.match root.to_s
11
+ config.paths["db/migrate"].expanded.each do |expanded_path|
12
+ app.config.paths["db/migrate"] << expanded_path
13
+ end
14
+ end
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ module Mailtime
2
+ # Functionality exists in a module for the same reasons as
3
+ # outlined in mail_template_concern.rb
4
+ module MailLogConcern
5
+
6
+ extend ::ActiveSupport::Concern
7
+
8
+ included do
9
+ self.table_name = 'mailtime_mail_logs'
10
+ belongs_to :user, :class_name => 'User',
11
+ :foreign_key => :user_id
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,30 @@
1
+ module Mailtime
2
+ # moving the functionality to this module, you can include
3
+ # this concern instead of sub-classing the `MailTemplate` model.
4
+ module MailTemplateConcern
5
+
6
+ extend ::ActiveSupport::Concern
7
+
8
+ included do
9
+ self.table_name = 'mailtime_mail_templates'
10
+
11
+ validates_presence_of :klass, :in => -> { mailers }
12
+ validates_uniqueness_of :action, :scope => :klass
13
+
14
+ def self.mailers
15
+ Mailtime.configuration.mailers
16
+ end
17
+
18
+ def self.mail_actions
19
+ mailers.collect { |mailer| [mailer, mailer.constantize.public_instance_methods(false)] }
20
+ end
21
+ end
22
+
23
+ def additional_headers
24
+ headers = {}
25
+ headers[:subject] = self.subject if self.subject.present?
26
+ headers
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,2 @@
1
+ require 'mailtime/active_record/models/mail_log'
2
+ require 'mailtime/active_record/models/mail_template'
@@ -0,0 +1,39 @@
1
+ require 'mailtime/models'
2
+ require 'mailtime/renderers/base_renderer'
3
+
4
+ module Mailtime
5
+ class Processor
6
+
7
+ def initialize(mail)
8
+ @mail = mail
9
+ end
10
+
11
+ def execute
12
+ create_mail_log if Mailtime.configuration.log
13
+ if Mailtime.configuration.render
14
+ renderer = Mailtime.configuration.renderer.to_s.constantize.new(@mail)
15
+ @mail.body = renderer.send(Mailtime.configuration.renderer_method)
16
+ end
17
+ @mail
18
+ end
19
+
20
+ protected
21
+
22
+ def create_mail_log
23
+ ::Mailtime::MailLog.create(
24
+ :user => User.find_by(:email =>@mail.to.first),
25
+ :mailtime_mail_template_id => @template.try(:id),
26
+ :action => @mail.mailer_action,
27
+ :klass => @mail.mailer_klass,
28
+ :headers => extract_headers
29
+ )
30
+ end
31
+
32
+ def extract_headers
33
+ headers = {}
34
+ @mail.header_fields.map { |k| headers[k.name] = k.value }
35
+ headers
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,7 @@
1
+ class Railtie < Rails::Railtie
2
+ initializer "Include your code in the controller" do
3
+ ActiveSupport.on_load(:action_controller) do
4
+ include Mailtime
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,24 @@
1
+ module Mailtime
2
+ module Renderers
3
+ class BaseRenderer
4
+
5
+ # we inject mail with the instance variables from your ActionMailer action.
6
+ # access them via mail.action_variables
7
+ def initialize(mail)
8
+ @mail = mail
9
+ @template = template
10
+ end
11
+
12
+ def render
13
+ @template.content
14
+ end
15
+
16
+ protected
17
+
18
+ def template
19
+ ::Mailtime::MailTemplate.find_by(:klass => @mail.mailer_klass, :action => @mail.mailer_action)
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ module Mailtime
2
+ VERSION = "0.1.0"
3
+ end
data/lib/mailtime.rb ADDED
@@ -0,0 +1,69 @@
1
+ begin
2
+ require 'rails/engine'
3
+ require 'mailtime/engine'
4
+ rescue LoadError
5
+
6
+ end
7
+
8
+ module Mailtime
9
+
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 :mailers, :render, :log, :fallback_to_erb, :renderer, :renderer_method, :lazy_load_mailers,
21
+ :user_class
22
+
23
+ def initialize
24
+ @lazy_load_mailers = false
25
+ @mailers = load_mailers
26
+ @render = true
27
+ @log = true
28
+ @fallback_to_erb = true
29
+ @renderer = 'Mailtime::Renderers::BaseRenderer'
30
+ @renderer_method = :render
31
+ @user_class = 'User'
32
+ @user_finder = nil
33
+ end
34
+
35
+ def load_mailers
36
+ mailers = []
37
+ unless @lazy_load_mailers
38
+ mailers = require_and_load_mailers
39
+ end
40
+ mailers
41
+ end
42
+
43
+ protected
44
+
45
+ def require_and_load_mailers
46
+ mailers = []
47
+ Dir.glob("#{::Rails.root}/app/mailers/**/*_mailer.rb").each do |m|
48
+ require m rescue nil
49
+ end
50
+ mailers << ::ActionMailer::Base.descendants.map(&:to_s)
51
+ mailers
52
+ end
53
+
54
+ end
55
+
56
+ protected
57
+
58
+ def self.find_user_by(attr = :email, value = nil)
59
+ ::User.find_by(attr => value)
60
+ end
61
+
62
+ end
63
+
64
+ require 'mailtime/action_mailer/base'
65
+ require 'mailtime/action_mailer/interceptor'
66
+ require 'mailtime/processor'
67
+ require 'mailtime/railtie'
68
+ require 'mailtime/mail_log_concern'
69
+ require 'mailtime/mail_template_concern'
data/mailtime.gemspec ADDED
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mailtime/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "mailtime"
8
+ spec.version = Mailtime::VERSION
9
+ spec.authors = ["Josh Brody"]
10
+ spec.email = ["josh@josh.mn"]
11
+
12
+ spec.summary = %q{Manage the mails you send from Rails.}
13
+ spec.homepage = "https://github.com/joshmn/mailtime"
14
+ spec.license = 'MIT'
15
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
16
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
17
+ if spec.respond_to?(:metadata)
18
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
19
+ else
20
+ raise "RubyGems 2.0 or newer is required to protect against " \
21
+ "public gem pushes."
22
+ end
23
+
24
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
25
+ f.match(%r{^(test|spec|features)/})
26
+ end
27
+
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ spec.add_development_dependency 'minitest', '~> 4.7.3'
33
+
34
+ spec.requirements << 'Rails <= 3.2'
35
+
36
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mailtime
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Josh Brody
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-04-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.7.3
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.7.3
27
+ description:
28
+ email:
29
+ - josh@josh.mn
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".gitignore"
35
+ - Gemfile
36
+ - MIT-LICENSE
37
+ - README.md
38
+ - Rakefile
39
+ - bin/console
40
+ - bin/setup
41
+ - lib/generators/mailtime/USAGE
42
+ - lib/generators/mailtime/install_generator.rb
43
+ - lib/generators/mailtime/templates/db/migrate/1_mailtime_migration.rb
44
+ - lib/generators/mailtime/templates/default_initializer.rb
45
+ - lib/mailtime.rb
46
+ - lib/mailtime/action_mailer/base.rb
47
+ - lib/mailtime/action_mailer/interceptor.rb
48
+ - lib/mailtime/active_record/models/mail_log.rb
49
+ - lib/mailtime/active_record/models/mail_template.rb
50
+ - lib/mailtime/engine.rb
51
+ - lib/mailtime/mail_log_concern.rb
52
+ - lib/mailtime/mail_template_concern.rb
53
+ - lib/mailtime/models.rb
54
+ - lib/mailtime/processor.rb
55
+ - lib/mailtime/railtie.rb
56
+ - lib/mailtime/renderers/base_renderer.rb
57
+ - lib/mailtime/version.rb
58
+ - mailtime.gemspec
59
+ homepage: https://github.com/joshmn/mailtime
60
+ licenses:
61
+ - MIT
62
+ metadata:
63
+ allowed_push_host: https://rubygems.org
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements:
79
+ - Rails <= 3.2
80
+ rubyforge_project:
81
+ rubygems_version: 2.4.3
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: Manage the mails you send from Rails.
85
+ test_files: []
86
+ has_rdoc: