action_mailer_kafka 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +158 -0
  3. data/.gitignore +18 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +64 -0
  6. data/Appraisals +21 -0
  7. data/CHANGELOG.md +6 -0
  8. data/Gemfile +4 -0
  9. data/LICENSE.md +23 -0
  10. data/README.md +138 -0
  11. data/Rakefile +6 -0
  12. data/action_mailer_kafka.gemspec +52 -0
  13. data/bin/console +14 -0
  14. data/bin/setup +8 -0
  15. data/example/.gitignore +21 -0
  16. data/example/Gemfile +39 -0
  17. data/example/README.rdoc +10 -0
  18. data/example/Rakefile +6 -0
  19. data/example/app/assets/images/.keep +0 -0
  20. data/example/app/assets/javascripts/application.js +16 -0
  21. data/example/app/assets/javascripts/users.js.coffee +3 -0
  22. data/example/app/assets/stylesheets/application.css +15 -0
  23. data/example/app/assets/stylesheets/scaffolds.css.scss +69 -0
  24. data/example/app/assets/stylesheets/users.css.scss +3 -0
  25. data/example/app/controllers/application_controller.rb +5 -0
  26. data/example/app/controllers/concerns/.keep +0 -0
  27. data/example/app/controllers/users_controller.rb +82 -0
  28. data/example/app/helpers/application_helper.rb +2 -0
  29. data/example/app/helpers/users_helper.rb +2 -0
  30. data/example/app/jobs/send_email_job.rb +8 -0
  31. data/example/app/mailers/.keep +0 -0
  32. data/example/app/mailers/example_mailer.rb +6 -0
  33. data/example/app/models/.keep +0 -0
  34. data/example/app/models/concerns/.keep +0 -0
  35. data/example/app/models/user.rb +2 -0
  36. data/example/app/views/example_mailer/sample_email.html.erb +398 -0
  37. data/example/app/views/example_mailer/sample_email.text.erb +2 -0
  38. data/example/app/views/layouts/application.html.erb +14 -0
  39. data/example/app/views/users/_form.html.erb +25 -0
  40. data/example/app/views/users/edit.html.erb +6 -0
  41. data/example/app/views/users/index.html.erb +27 -0
  42. data/example/app/views/users/index.json.jbuilder +4 -0
  43. data/example/app/views/users/new.html.erb +5 -0
  44. data/example/app/views/users/show.html.erb +14 -0
  45. data/example/app/views/users/show.json.jbuilder +1 -0
  46. data/example/config/application.rb +23 -0
  47. data/example/config/boot.rb +4 -0
  48. data/example/config/database.yml +11 -0
  49. data/example/config/environment.rb +5 -0
  50. data/example/config/environments/development.rb +43 -0
  51. data/example/config/environments/production.rb +105 -0
  52. data/example/config/environments/test.rb +39 -0
  53. data/example/config/initializers/backtrace_silencers.rb +7 -0
  54. data/example/config/initializers/cookies_serializer.rb +3 -0
  55. data/example/config/initializers/filter_parameter_logging.rb +4 -0
  56. data/example/config/initializers/inflections.rb +16 -0
  57. data/example/config/initializers/mime_types.rb +4 -0
  58. data/example/config/initializers/session_store.rb +3 -0
  59. data/example/config/initializers/wrap_parameters.rb +14 -0
  60. data/example/config/locales/en.yml +23 -0
  61. data/example/config/routes.rb +4 -0
  62. data/example/config/secrets.yml +22 -0
  63. data/example/config.ru +4 -0
  64. data/example/db/migrate/20141111080045_create_users.rb +10 -0
  65. data/example/db/migrate/20141115060216_create_delayed_jobs.rb +22 -0
  66. data/example/db/schema.rb +40 -0
  67. data/example/db/seeds.rb +7 -0
  68. data/example/public/404.html +67 -0
  69. data/example/public/422.html +67 -0
  70. data/example/public/500.html +66 -0
  71. data/example/public/favicon.ico +0 -0
  72. data/example/public/robots.txt +5 -0
  73. data/example/vendor/assets/javascripts/.keep +0 -0
  74. data/example/vendor/assets/stylesheets/.keep +0 -0
  75. data/gemfiles/.bundle/config +2 -0
  76. data/gemfiles/mail_2_5.gemfile +7 -0
  77. data/gemfiles/mail_2_6.gemfile +7 -0
  78. data/gemfiles/mail_2_7.gemfile +7 -0
  79. data/gemfiles/rails_4.gemfile +7 -0
  80. data/gemfiles/rails_5.gemfile +7 -0
  81. data/lib/action_mailer_kafka/delivery_method.rb +139 -0
  82. data/lib/action_mailer_kafka/error.rb +22 -0
  83. data/lib/action_mailer_kafka/railtie.rb +7 -0
  84. data/lib/action_mailer_kafka/version.rb +3 -0
  85. data/lib/action_mailer_kafka.rb +10 -0
  86. data/logo.png +0 -0
  87. metadata +328 -0
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,52 @@
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'action_mailer_kafka/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'action_mailer_kafka'
7
+ spec.version = ActionMailerKafka::VERSION
8
+ spec.authors = ['Luong Vo']
9
+ spec.email = ['vo.tran.thanh.luong@gmail.com']
10
+ spec.license = 'MIT'
11
+ spec.summary = 'Custom action mailer to send mails to Kafka message queue.'
12
+ spec.description = 'This gem defines a way for Rails service or other backends to \
13
+ define a mailer that sends email to our employemt hero mail service.'
14
+ spec.homepage = 'https://github.com/luong-komorebi/action-mailer-kafka/'
15
+
16
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
18
+ if spec.respond_to?(:metadata)
19
+ # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
20
+
21
+ spec.metadata['homepage_uri'] = spec.homepage
22
+ # spec.metadata['source_code_uri'] = "TODO: Put your gem's public repo URL here."
23
+ # spec.metadata['changelog_uri'] = "TODO: Put your gem's CHANGELOG.md URL here."
24
+ else
25
+ raise 'RubyGems 2.0 or newer is required to protect against ' \
26
+ 'public gem pushes.'
27
+ end
28
+
29
+ # Specify which files should be added to the gem when it is released.
30
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
31
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
32
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
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'
39
+ spec.add_dependency 'ruby-kafka', '~> 0.7.6'
40
+ spec.add_development_dependency 'appraisal'
41
+ spec.add_development_dependency 'bundler'
42
+ spec.add_development_dependency 'byebug'
43
+ spec.add_development_dependency 'faraday'
44
+ spec.add_development_dependency 'rails'
45
+ spec.add_development_dependency 'rake'
46
+ spec.add_development_dependency 'rspec'
47
+ spec.add_development_dependency 'rspec-json_expectations'
48
+ spec.add_development_dependency 'rubocop'
49
+ spec.add_development_dependency 'rubocop-rspec'
50
+ spec.add_development_dependency 'rubycritic'
51
+ spec.add_development_dependency 'simplecov'
52
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "action_mailer_kafka"
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__)
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,21 @@
1
+ # See https://help.github.com/articles/ignoring-files for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile '~/.gitignore_global'
6
+
7
+ # Ignore bundler config.
8
+ /.bundle
9
+
10
+ # Ignore the default SQLite database.
11
+ /db/*.sqlite3
12
+ /db/*.sqlite3-journal
13
+
14
+ # Ignore all logfiles and tempfiles.
15
+ /log/*.log
16
+ /tmp
17
+
18
+ # Ignore application configuration
19
+ /config/application.yml
20
+
21
+ /Gemfile.lock
data/example/Gemfile ADDED
@@ -0,0 +1,39 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'byebug'
4
+ # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
5
+ gem 'rails'
6
+ gem 'pg'
7
+ # Use SCSS for stylesheets
8
+ # gem 'sass-rails', '~> 4.0.3'
9
+ # Use Uglifier as compressor for JavaScript assets
10
+ gem 'uglifier'
11
+ # Use CoffeeScript for .js.coffee assets and view
12
+ gem 'coffee-rails'
13
+ # See https://github.com/sstephenson/execjs#readme for more supported runtimes
14
+ # gem 'therubyracer', platforms: :ruby
15
+
16
+ # Use jquery as the JavaScript library
17
+ gem 'jquery-rails'
18
+ # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
19
+ gem 'turbolinks'
20
+ # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
21
+ gem 'jbuilder'
22
+
23
+ # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
24
+ gem 'spring', group: :development
25
+
26
+ # Use ActiveModel has_secure_password
27
+ # gem 'bcrypt', '~> 3.1.7'
28
+
29
+ # Use unicorn as the app server
30
+ # gem 'unicorn'
31
+
32
+ # Use Capistrano for deployment
33
+ # gem 'capistrano-rails', group: :development
34
+
35
+ # Use debugger
36
+ # gem 'debugger', group: [:development, :test]
37
+ gem "figaro"
38
+ gem 'delayed_job_active_record'
39
+ gem 'action_mailer_kafka', path: '../'
@@ -0,0 +1,10 @@
1
+ == README
2
+
3
+ Simple application for sending mails from rails application.
4
+
5
+ ```sh
6
+ bundle exec rake db:create
7
+ bundle exec rake db:migrate
8
+ bundle exec rackup
9
+ ```
10
+
data/example/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+
6
+ Rails.application.load_tasks
File without changes
@@ -0,0 +1,16 @@
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 vendor/assets/javascripts of plugins, if any, 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.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require jquery
14
+ //= require jquery_ujs
15
+ //= require turbolinks
16
+ //= require_tree .
@@ -0,0 +1,3 @@
1
+ # Place all the behaviors and hooks related to the matching controller here.
2
+ # All this logic will automatically be available in application.js.
3
+ # You can use CoffeeScript in this file: http://coffeescript.org/
@@ -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 vendor/assets/stylesheets of plugins, if any, 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 styles
10
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
+ * file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,69 @@
1
+ body {
2
+ background-color: #fff;
3
+ color: #333;
4
+ font-family: verdana, arial, helvetica, sans-serif;
5
+ font-size: 13px;
6
+ line-height: 18px;
7
+ }
8
+
9
+ p, ol, ul, td {
10
+ font-family: verdana, arial, helvetica, sans-serif;
11
+ font-size: 13px;
12
+ line-height: 18px;
13
+ }
14
+
15
+ pre {
16
+ background-color: #eee;
17
+ padding: 10px;
18
+ font-size: 11px;
19
+ }
20
+
21
+ a {
22
+ color: #000;
23
+ &:visited {
24
+ color: #666;
25
+ }
26
+ &:hover {
27
+ color: #fff;
28
+ background-color: #000;
29
+ }
30
+ }
31
+
32
+ div {
33
+ &.field, &.actions {
34
+ margin-bottom: 10px;
35
+ }
36
+ }
37
+
38
+ #notice {
39
+ color: green;
40
+ }
41
+
42
+ .field_with_errors {
43
+ padding: 2px;
44
+ background-color: red;
45
+ display: table;
46
+ }
47
+
48
+ #error_explanation {
49
+ width: 450px;
50
+ border: 2px solid red;
51
+ padding: 7px;
52
+ padding-bottom: 0;
53
+ margin-bottom: 20px;
54
+ background-color: #f0f0f0;
55
+ h2 {
56
+ text-align: left;
57
+ font-weight: bold;
58
+ padding: 5px 5px 5px 15px;
59
+ font-size: 12px;
60
+ margin: -7px;
61
+ margin-bottom: 0px;
62
+ background-color: #c00;
63
+ color: #fff;
64
+ }
65
+ ul li {
66
+ font-size: 12px;
67
+ list-style: square;
68
+ }
69
+ }
@@ -0,0 +1,3 @@
1
+ // Place all the styles related to the users controller here.
2
+ // They will automatically be included in application.css.
3
+ // You can use Sass (SCSS) here: http://sass-lang.com/
@@ -0,0 +1,5 @@
1
+ class ApplicationController < ActionController::Base
2
+ # Prevent CSRF attacks by raising an exception.
3
+ # For APIs, you may want to use :null_session instead.
4
+ protect_from_forgery with: :exception
5
+ end
File without changes
@@ -0,0 +1,82 @@
1
+ class UsersController < ApplicationController
2
+ before_action :set_user, only: [:show, :edit, :update, :destroy]
3
+
4
+ # GET /users
5
+ # GET /users.json
6
+ def index
7
+ @users = User.all
8
+ end
9
+
10
+ # GET /users/1
11
+ # GET /users/1.json
12
+ def show
13
+ end
14
+
15
+ # GET /users/new
16
+ def new
17
+ @user = User.new
18
+ end
19
+
20
+ # GET /users/1/edit
21
+ def edit
22
+ end
23
+
24
+ # POST /users
25
+ # POST /users.json
26
+ def create
27
+ @user = User.new(user_params)
28
+
29
+ respond_to do |format|
30
+ if @user.save
31
+
32
+ # Sends email to user when user is created.
33
+ # To send emails without Action Job
34
+ ExampleMailer.sample_email(@user).deliver_now
35
+
36
+ # To send emails using Action Jobs
37
+ # SendEmailJob.set(wait: 10.seconds).perform_later(@user)
38
+
39
+ format.html { redirect_to @user, notice: 'User was successfully created.' }
40
+ format.json { render :show, status: :created, location: @user }
41
+ else
42
+ format.html { render :new }
43
+ format.json { render json: @user.errors, status: :unprocessable_entity }
44
+ end
45
+ end
46
+ end
47
+
48
+ # PATCH/PUT /users/1
49
+ # PATCH/PUT /users/1.json
50
+ def update
51
+ respond_to do |format|
52
+ if @user.update(user_params)
53
+ format.html { redirect_to @user, notice: 'User was successfully updated.' }
54
+ format.json { render :show, status: :ok, location: @user }
55
+ else
56
+ format.html { render :edit }
57
+ format.json { render json: @user.errors, status: :unprocessable_entity }
58
+ end
59
+ end
60
+ end
61
+
62
+ # DELETE /users/1
63
+ # DELETE /users/1.json
64
+ def destroy
65
+ @user.destroy
66
+ respond_to do |format|
67
+ format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
68
+ format.json { head :no_content }
69
+ end
70
+ end
71
+
72
+ private
73
+ # Use callbacks to share common setup or constraints between actions.
74
+ def set_user
75
+ @user = User.find(params[:id])
76
+ end
77
+
78
+ # Never trust parameters from the scary internet, only allow the white list through.
79
+ def user_params
80
+ params.require(:user).permit(:name, :email)
81
+ end
82
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
@@ -0,0 +1,2 @@
1
+ module UsersHelper
2
+ end
@@ -0,0 +1,8 @@
1
+ class SendEmailJob < ActiveJob::Base
2
+ queue_as :default
3
+
4
+ def perform(user)
5
+ @user = user
6
+ ExampleMailer.sample_email(@user).deliver_now
7
+ end
8
+ end
File without changes
@@ -0,0 +1,6 @@
1
+ class ExampleMailer < ActionMailer::Base
2
+ def sample_email(user)
3
+ @user = user
4
+ mail(to: @user.email, subject: 'Sample Email', user: @user)
5
+ end
6
+ end
File without changes
File without changes
@@ -0,0 +1,2 @@
1
+ class User < ActiveRecord::Base
2
+ end
@@ -0,0 +1,398 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta name="viewport" content="width=device-width" />
5
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
6
+ <title>Simple Transactional Email</title>
7
+ <style>
8
+ /* -------------------------------------
9
+ GLOBAL RESETS
10
+ ------------------------------------- */
11
+
12
+ /*All the styling goes here*/
13
+
14
+ img {
15
+ border: none;
16
+ -ms-interpolation-mode: bicubic;
17
+ max-width: 100%;
18
+ }
19
+
20
+ body {
21
+ background-color: #f6f6f6;
22
+ font-family: sans-serif;
23
+ -webkit-font-smoothing: antialiased;
24
+ font-size: 14px;
25
+ line-height: 1.4;
26
+ margin: 0;
27
+ padding: 0;
28
+ -ms-text-size-adjust: 100%;
29
+ -webkit-text-size-adjust: 100%;
30
+ }
31
+
32
+ table {
33
+ border-collapse: separate;
34
+ mso-table-lspace: 0pt;
35
+ mso-table-rspace: 0pt;
36
+ width: 100%; }
37
+ table td {
38
+ font-family: sans-serif;
39
+ font-size: 14px;
40
+ vertical-align: top;
41
+ }
42
+
43
+ /* -------------------------------------
44
+ BODY & CONTAINER
45
+ ------------------------------------- */
46
+
47
+ .body {
48
+ background-color: #f6f6f6;
49
+ width: 100%;
50
+ }
51
+
52
+ /* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
53
+ .container {
54
+ display: block;
55
+ margin: 0 auto !important;
56
+ /* makes it centered */
57
+ max-width: 580px;
58
+ padding: 10px;
59
+ width: 580px;
60
+ }
61
+
62
+ /* This should also be a block element, so that it will fill 100% of the .container */
63
+ .content {
64
+ box-sizing: border-box;
65
+ display: block;
66
+ margin: 0 auto;
67
+ max-width: 580px;
68
+ padding: 10px;
69
+ }
70
+
71
+ /* -------------------------------------
72
+ HEADER, FOOTER, MAIN
73
+ ------------------------------------- */
74
+ .main {
75
+ background: #ffffff;
76
+ border-radius: 3px;
77
+ width: 100%;
78
+ }
79
+
80
+ .wrapper {
81
+ box-sizing: border-box;
82
+ padding: 20px;
83
+ }
84
+
85
+ .content-block {
86
+ padding-bottom: 10px;
87
+ padding-top: 10px;
88
+ }
89
+
90
+ .footer {
91
+ clear: both;
92
+ margin-top: 10px;
93
+ text-align: center;
94
+ width: 100%;
95
+ }
96
+ .footer td,
97
+ .footer p,
98
+ .footer span,
99
+ .footer a {
100
+ color: #999999;
101
+ font-size: 12px;
102
+ text-align: center;
103
+ }
104
+
105
+ /* -------------------------------------
106
+ TYPOGRAPHY
107
+ ------------------------------------- */
108
+ h1,
109
+ h2,
110
+ h3,
111
+ h4 {
112
+ color: #000000;
113
+ font-family: sans-serif;
114
+ font-weight: 400;
115
+ line-height: 1.4;
116
+ margin: 0;
117
+ margin-bottom: 30px;
118
+ }
119
+
120
+ h1 {
121
+ font-size: 35px;
122
+ font-weight: 300;
123
+ text-align: center;
124
+ text-transform: capitalize;
125
+ }
126
+
127
+ p,
128
+ ul,
129
+ ol {
130
+ font-family: sans-serif;
131
+ font-size: 14px;
132
+ font-weight: normal;
133
+ margin: 0;
134
+ margin-bottom: 15px;
135
+ }
136
+ p li,
137
+ ul li,
138
+ ol li {
139
+ list-style-position: inside;
140
+ margin-left: 5px;
141
+ }
142
+
143
+ a {
144
+ color: #3498db;
145
+ text-decoration: underline;
146
+ }
147
+
148
+ /* -------------------------------------
149
+ BUTTONS
150
+ ------------------------------------- */
151
+ .btn {
152
+ box-sizing: border-box;
153
+ width: 100%; }
154
+ .btn > tbody > tr > td {
155
+ padding-bottom: 15px; }
156
+ .btn table {
157
+ width: auto;
158
+ }
159
+ .btn table td {
160
+ background-color: #ffffff;
161
+ border-radius: 5px;
162
+ text-align: center;
163
+ }
164
+ .btn a {
165
+ background-color: #ffffff;
166
+ border: solid 1px #3498db;
167
+ border-radius: 5px;
168
+ box-sizing: border-box;
169
+ color: #3498db;
170
+ cursor: pointer;
171
+ display: inline-block;
172
+ font-size: 14px;
173
+ font-weight: bold;
174
+ margin: 0;
175
+ padding: 12px 25px;
176
+ text-decoration: none;
177
+ text-transform: capitalize;
178
+ }
179
+
180
+ .btn-primary table td {
181
+ background-color: #3498db;
182
+ }
183
+
184
+ .btn-primary a {
185
+ background-color: #3498db;
186
+ border-color: #3498db;
187
+ color: #ffffff;
188
+ }
189
+
190
+ /* -------------------------------------
191
+ OTHER STYLES THAT MIGHT BE USEFUL
192
+ ------------------------------------- */
193
+ .last {
194
+ margin-bottom: 0;
195
+ }
196
+
197
+ .first {
198
+ margin-top: 0;
199
+ }
200
+
201
+ .align-center {
202
+ text-align: center;
203
+ }
204
+
205
+ .align-right {
206
+ text-align: right;
207
+ }
208
+
209
+ .align-left {
210
+ text-align: left;
211
+ }
212
+
213
+ .clear {
214
+ clear: both;
215
+ }
216
+
217
+ .mt0 {
218
+ margin-top: 0;
219
+ }
220
+
221
+ .mb0 {
222
+ margin-bottom: 0;
223
+ }
224
+
225
+ .preheader {
226
+ color: transparent;
227
+ display: none;
228
+ height: 0;
229
+ max-height: 0;
230
+ max-width: 0;
231
+ opacity: 0;
232
+ overflow: hidden;
233
+ mso-hide: all;
234
+ visibility: hidden;
235
+ width: 0;
236
+ }
237
+
238
+ .powered-by a {
239
+ text-decoration: none;
240
+ }
241
+
242
+ hr {
243
+ border: 0;
244
+ border-bottom: 1px solid #f6f6f6;
245
+ margin: 20px 0;
246
+ }
247
+
248
+ /* -------------------------------------
249
+ RESPONSIVE AND MOBILE FRIENDLY STYLES
250
+ ------------------------------------- */
251
+ @media only screen and (max-width: 620px) {
252
+ table[class=body] h1 {
253
+ font-size: 28px !important;
254
+ margin-bottom: 10px !important;
255
+ }
256
+ table[class=body] p,
257
+ table[class=body] ul,
258
+ table[class=body] ol,
259
+ table[class=body] td,
260
+ table[class=body] span,
261
+ table[class=body] a {
262
+ font-size: 16px !important;
263
+ }
264
+ table[class=body] .wrapper,
265
+ table[class=body] .article {
266
+ padding: 10px !important;
267
+ }
268
+ table[class=body] .content {
269
+ padding: 0 !important;
270
+ }
271
+ table[class=body] .container {
272
+ padding: 0 !important;
273
+ width: 100% !important;
274
+ }
275
+ table[class=body] .main {
276
+ border-left-width: 0 !important;
277
+ border-radius: 0 !important;
278
+ border-right-width: 0 !important;
279
+ }
280
+ table[class=body] .btn table {
281
+ width: 100% !important;
282
+ }
283
+ table[class=body] .btn a {
284
+ width: 100% !important;
285
+ }
286
+ table[class=body] .img-responsive {
287
+ height: auto !important;
288
+ max-width: 100% !important;
289
+ width: auto !important;
290
+ }
291
+ }
292
+
293
+ /* -------------------------------------
294
+ PRESERVE THESE STYLES IN THE HEAD
295
+ ------------------------------------- */
296
+ @media all {
297
+ .ExternalClass {
298
+ width: 100%;
299
+ }
300
+ .ExternalClass,
301
+ .ExternalClass p,
302
+ .ExternalClass span,
303
+ .ExternalClass font,
304
+ .ExternalClass td,
305
+ .ExternalClass div {
306
+ line-height: 100%;
307
+ }
308
+ .apple-link a {
309
+ color: inherit !important;
310
+ font-family: inherit !important;
311
+ font-size: inherit !important;
312
+ font-weight: inherit !important;
313
+ line-height: inherit !important;
314
+ text-decoration: none !important;
315
+ }
316
+ .btn-primary table td:hover {
317
+ background-color: #34495e !important;
318
+ }
319
+ .btn-primary a:hover {
320
+ background-color: #34495e !important;
321
+ border-color: #34495e !important;
322
+ }
323
+ }
324
+
325
+ </style>
326
+ </head>
327
+ <body class="">
328
+ <span class="preheader">This is preheader text. Some clients will show this text as a preview.</span>
329
+ <table role="presentation" border="0" cellpadding="0" cellspacing="0" class="body">
330
+ <tr>
331
+ <td>&nbsp;</td>
332
+ <td class="container">
333
+ <div class="content">
334
+
335
+ <!-- START CENTERED WHITE CONTAINER -->
336
+ <table role="presentation" class="main">
337
+
338
+ <!-- START MAIN CONTENT AREA -->
339
+ <tr>
340
+ <td class="wrapper">
341
+ <table role="presentation" border="0" cellpadding="0" cellspacing="0">
342
+ <tr>
343
+ <td>
344
+ <p>Hi there,</p>
345
+ <p>Sometimes you just want to send a simple HTML email with a simple design and clear call to action. This is it.</p>
346
+ <table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
347
+ <tbody>
348
+ <tr>
349
+ <td align="left">
350
+ <table role="presentation" border="0" cellpadding="0" cellspacing="0">
351
+ <tbody>
352
+ <tr>
353
+ <td> <a href="http://htmlemail.io" target="_blank">Call To Action</a> </td>
354
+ </tr>
355
+ </tbody>
356
+ </table>
357
+ </td>
358
+ </tr>
359
+ </tbody>
360
+ </table>
361
+ <p>This is a really simple email template. Its sole purpose is to get the recipient to click the button with no distractions.</p>
362
+ <p>Good luck! Hope it works.</p>
363
+ </td>
364
+ </tr>
365
+ </table>
366
+ </td>
367
+ </tr>
368
+
369
+ <!-- END MAIN CONTENT AREA -->
370
+ </table>
371
+ <!-- END CENTERED WHITE CONTAINER -->
372
+
373
+ <!-- START FOOTER -->
374
+ <div class="footer">
375
+ <table role="presentation" border="0" cellpadding="0" cellspacing="0">
376
+ <tr>
377
+ <td class="content-block">
378
+ <span class="apple-link">Company Inc, 3 Abbey Road, San Francisco CA 94102</span>
379
+ <br> Don't like these emails? <a href="http://i.imgur.com/CScmqnj.gif">Unsubscribe</a>.
380
+ </td>
381
+ </tr>
382
+ <tr>
383
+ <td class="content-block powered-by">
384
+ Powered by <a href="http://htmlemail.io">HTMLemail</a>.
385
+ </td>
386
+ </tr>
387
+ </table>
388
+ </div>
389
+ <!-- END FOOTER -->
390
+
391
+ </div>
392
+ </td>
393
+ <td>&nbsp;</td>
394
+ </tr>
395
+ </table>
396
+ </body>
397
+ </html>
398
+