├── .circleci └── config.yml ├── .document ├── .gitignore ├── CHANGELOG.rdoc ├── CONTRIBUTING.md ├── Gemfile ├── LICENSE ├── README.md ├── RELEASE.md ├── Rakefile ├── lib ├── postmark-rails.rb └── postmark-rails │ ├── preview_interceptor.rb │ ├── railtie.rb │ ├── templated_mailer.rb │ └── version.rb ├── postmark-rails.gemspec ├── postmark.png └── spec ├── fixtures ├── empty.gif ├── models │ └── test_mailer.rb └── views │ └── test_mailer │ ├── message_with_attachment.erb │ ├── message_with_inline_image.html.erb │ ├── message_with_metadata.text.erb │ ├── multipart_message.html.erb │ ├── multipart_message.text.erb │ ├── simple_message.erb │ ├── tagged_message.erb │ └── tracked_message.html.erb ├── integration ├── batch_delivery_spec.rb └── delivery_spec.rb ├── spec.opts ├── spec_helper.rb └── unit ├── postmark-rails_spec.rb ├── preview_interceptor_spec.rb └── templated_mailer_spec.rb /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | orbs: 4 | ruby: circleci/ruby@1.8.0 5 | 6 | jobs: 7 | build: 8 | parameters: 9 | ruby_version: 10 | type: string 11 | rails_version: 12 | type: string 13 | mime_types_version: 14 | type: string 15 | default: "~> 3.1" 16 | docker: 17 | - image: cimg/ruby:<< parameters.ruby_version >> 18 | executor: ruby/default 19 | environment: 20 | RAILS_TEST_VERSION: << parameters.rails_version >> 21 | MIME_TYPES_TEST_VERSION: << parameters.mime_types_version >> 22 | steps: 23 | - checkout 24 | - ruby/install-deps: 25 | bundler-version: 2.2.3 26 | path: vendor/bundle/rails-<< parameters.rails_version>> 27 | with-cache: false # requires Gemfile.lock 28 | - run: 29 | name: Run tests 30 | command: bundle exec rake spec 31 | 32 | workflows: 33 | tests: 34 | jobs: 35 | - build: 36 | matrix: 37 | alias: Rails 3 38 | parameters: 39 | rails_version: ["~> 3.0", "~> 3.2"] 40 | ruby_version: ["2.5"] 41 | mime_types_version: ["1.25.1"] 42 | - build: 43 | matrix: 44 | alias: Rails 4 45 | parameters: 46 | rails_version: ["~> 4.0", "~> 4.1", "~> 4.2"] 47 | ruby_version: ["2.5"] 48 | - build: 49 | matrix: 50 | alias: Rails 5 51 | parameters: 52 | rails_version: ["~> 5.0", "~> 5.1", "~> 5.2"] 53 | ruby_version: ["2.5", "2.6", "2.7"] 54 | - build: 55 | matrix: 56 | alias: Rails 6 57 | parameters: 58 | rails_version: ["~> 6.0"] 59 | ruby_version: ["2.5", "2.6", "2.7"] 60 | - build: 61 | matrix: 62 | alias: Rails 7 63 | parameters: 64 | rails_version: ["~> 7.0"] 65 | ruby_version: ["2.7"] 66 | -------------------------------------------------------------------------------- /.document: -------------------------------------------------------------------------------- 1 | README.rdoc 2 | lib/**/*.rb 3 | bin/* 4 | features/**/*.feature 5 | LICENSE 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.sw? 2 | .DS_Store 3 | coverage 4 | rdoc 5 | pkg 6 | .rake_tasks 7 | .bundle 8 | .rvmrc 9 | Gemfile.lock 10 | gemfiles/*.lock 11 | **/*.idea 12 | -------------------------------------------------------------------------------- /CHANGELOG.rdoc: -------------------------------------------------------------------------------- 1 | = Changelog 2 | 3 | == 0.22.1 4 | * Migrated to ActiveCampaign 5 | 6 | == 0.22.0 7 | 8 | * Added support for Rails 7 9 | 10 | == 0.21.0 11 | 12 | * Update minimum postmark gem dependency to avoid use of TLS v1 13 | 14 | == 0.20.0 15 | 16 | * Update the postmark gem dependency to 1.x 17 | * Added support for Rails 6 18 | * Dropped support for Ruby 1.8.7 and 1.9.3 19 | * Added support for Ruby 2.7 20 | 21 | == 0.19.0 22 | 23 | * Update the postmark gem dependency to 1.15.x. 24 | * Added support for templated mailers. 25 | * Added source_code_uri to the gemspec. 26 | * Tested against all stable versions of ActionMailer 3.0-5.2 and Ruby 1.8.7-2.6.0. 27 | 28 | == 0.18.0 29 | 30 | * Update the postmark gem dependency to 1.14.x. 31 | 32 | == 0.17.0 33 | 34 | * Add support for metadata. 35 | * Update the postmark gem dependency to 1.13.x. 36 | 37 | == 0.16.0 38 | 39 | * Update the postmark gem dependency to 1.11.x. 40 | * Added a section on error handling to the README. 41 | 42 | == 0.15.0 43 | 44 | * Update the postmark gem dependency to 1.10.x. 45 | 46 | == 0.14.0 47 | 48 | * Update the postmark gem dependency to 1.9.x. 49 | 50 | == 0.13.0 51 | 52 | * Update the postmark gem dependency to 1.8.x. 53 | * Verified ActionMailer 5.0 support. 54 | 55 | == 0.12.0 56 | 57 | * Updated the postmark gem dependency to 1.7.x. 58 | 59 | == 0.11.0 60 | 61 | * Updated the postmark gem dependency to 1.6.x. 62 | 63 | == 0.10.0 64 | 65 | * Updated the postmark gem dependency to 1.5.x 66 | * Called API access strings tokens instead of keys in documentation and code. Kept backwards compatibility. 67 | 68 | == 0.9.0 69 | 70 | * Enabled HTTPS by default. 71 | * Added custom User-Agent header. 72 | * Updated the postmark gem dependency to 1.4.x. 73 | 74 | == 0.8.0 75 | 76 | * Added support for open tracking. 77 | * Updated the postmark gem dependency to 1.3.x. 78 | 79 | == 0.7.0 80 | 81 | * Updated the postmark gem dependency to 1.2.x. 82 | 83 | == 0.6.0 84 | 85 | * Updated the postmark gem dependency. 86 | * Inherited inline images support. 87 | 88 | == 0.5.2 89 | 90 | * Removed the legacy code providing Rails 2 support. 91 | * Added a Railtie for proper initialization in Rails 3+. 92 | * Removed the post-install message. 93 | 94 | == 0.5.1 95 | 96 | * Upgraded actionmailer dependency to use >= 3.0.0. 97 | * Added multiple gemfiles to test against multiple actionmailer versions (currently 3.0.x, 3.2.x, 4.0.x). 98 | 99 | == 0.5.0 100 | 101 | * Added integration specs. 102 | * Updated the postmark gem dependency to 1.0.x. 103 | * Removed attachments fix. 104 | * Replaced README.rdoc with README.md. 105 | * Added unit and integration tests for messages with attachemtns. 106 | * Added batch delivery support. 107 | 108 | == 0.4.2 109 | 110 | * Updated the gem’s environment. 111 | * Fixed the postmark gem dependency on 0.9.x. 112 | * Added Travis-CI for integration testing. 113 | 114 | == 0.4.1 115 | 116 | * Fixed "returning" deprecation warning. 117 | 118 | == 0.4.0 119 | 120 | * Attachments support. 121 | 122 | == 0.3.0 123 | 124 | * Added support for Rails 3. 125 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Before you report an issue or submit a pull request 2 | 3 | *If you are blocked or need help with Postmark, please [contact 4 | Postmark Support](https://postmarkapp.com/contact)*. For other, non-urgent 5 | cases you’re welcome to report a bug and/or contribute to this project. We will 6 | make our best effort to review your contributions and triage any bug reports in 7 | a timely fashion. 8 | 9 | If you’d like to submit a pull request: 10 | 11 | * Fork the project. 12 | * Make your feature addition or bug fix. 13 | * Add tests for it. This is important to prevent future regressions. 14 | * Do not mess with rakefile, version, or history. 15 | * Update the CHANGELOG, list your changes under Unreleased. 16 | * Update the README if necessary. 17 | * Write short, descriptive commit messages, following the format used in therepo. 18 | * Send a pull request. Bonus points for topic branches. 19 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | gemspec 4 | 5 | gem 'actionmailer', ENV.fetch('RAILS_TEST_VERSION', '~> 7.0') 6 | 7 | group :test do 8 | gem 'rspec', '~> 3.7' 9 | gem 'mime-types', ENV.fetch('MIME_TYPES_TEST_VERSION', '~> 3.1') 10 | end 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 Wildbit LLC. 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. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Postmark Logo 3 | 4 | 5 | # Postmark Rails Gem 6 | 7 | [![CircleCI](https://dl.circleci.com/status-badge/img/gh/ActiveCampaign/postmark-rails/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/ActiveCampaign/postmark-rails/tree/main) 8 | [![Code Climate](https://codeclimate.com/github/ActiveCampaign/postmark-rails/badges/gpa.svg)](https://codeclimate.com/github/ActiveCampaign/postmark-rails) 9 | [![License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](http://www.opensource.org/licenses/MIT) 10 | [![Gem Version](https://badge.fury.io/rb/postmark-rails.svg)](https://badge.fury.io/rb/postmark-rails) 11 | 12 | [Postmark](https://postmarkapp.com) allows you to send your emails with high delivery rates. 13 | It also includes detailed statistics. In addition, Postmark can parse incoming emails which are forwarded back to your application. 14 | 15 | The Postmark Rails Gem is a drop-in plug-in for ActionMailer to send emails via [Postmark](https://postmarkapp.com). 16 | The gem has been created for fast implementation and fully supports all of [Postmark’s features](https://postmarkapp.com/why). 17 | 18 | ## Usage 19 | 20 | Please see the [wiki](https://github.com/ActiveCampaign/postmark-rails/wiki) for detailed instructions about library features. 21 | For details about Postmark API in general, please check out [Postmark developer docs](https://postmarkapp.com/developer). 22 | 23 | ## Requirements 24 | 25 | You will need a Postmark account, server and sender signature (or verified domain) set up to use it. 26 | For details about setup, check out [wiki pages](https://github.com/ActiveCampaign/postmark-rails/wiki/Getting-Started). 27 | 28 | Also you will need a [postmark gem](https://github.com/ActiveCampaign/postmark-gem) version 1.0 and higher is required. 29 | 30 | ### Supported Rails Versions 31 | 32 | - Rails 7.0 33 | - Rails 6.0 34 | - Rails 5.0 35 | - Rails 4.x 36 | - Rails 3.x 37 | 38 | For Rails 2.3 please take a look at [version 0.4](https://github.com/ActiveCampaign/postmark-rails/tree/v0.4.2). 39 | It may miss some new features, but receives all required bug fixes and other support if needed. 40 | 41 | ## Installation 42 | 43 | Add `postmark-rails` to your Gemfile and run `bundle install`. 44 | 45 | ```ruby 46 | gem 'postmark-rails' 47 | ``` 48 | 49 | ## Rails 6-7 50 | 51 | Save your Postmark Server API Token to [config/credentials.yml.enc](https://guides.rubyonrails.org/security.html#custom-credentials): 52 | 53 | run `rails secret`, then run `rails credentials:edit` and add: 54 | 55 | ```yaml 56 | postmark_api_token: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 57 | ``` 58 | 59 | Set Postmark as your preferred mail delivery method via `config/application.rb`: 60 | 61 | ```ruby 62 | config.action_mailer.delivery_method = :postmark 63 | config.action_mailer.postmark_settings = { api_token: Rails.application.credentials.postmark_api_token } 64 | ``` 65 | 66 | ## Rails 3-5 67 | 68 | Save your Postmark Server API token to [config/secrets.yml](http://guides.rubyonrails.org/4_1_release_notes.html#config-secrets-yml). 69 | 70 | ```yaml 71 | postmark_api_token: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 72 | ``` 73 | 74 | Set Postmark as your preferred mail delivery method via `config/application.rb`: 75 | 76 | ```ruby 77 | config.action_mailer.delivery_method = :postmark 78 | config.action_mailer.postmark_settings = { :api_token => Rails.application.secrets.postmark_api_token } 79 | ``` 80 | 81 | --- 82 | 83 | **Note**: The `postmark_settings` hash can contain [any options](https://github.com/ActiveCampaign/postmark-gem#communicating-with-the-api) supported by `Postmark::ApiClient`. 84 | 85 | ### Additional information 86 | 87 | Looking for the advanced usage examples? Check out [the documentation](https://github.com/ActiveCampaign/postmark-gem/blob/main/README.md) for the [postmark gem](https://github.com/ActiveCampaign/postmark-gem). 88 | The `postmark-rails` gem is built on top of it, so you can benefit from all it's features. 89 | 90 | ## Note on Patches/Pull Requests 91 | 92 | See [CONTRIBUTING.md](CONTRIBUTING.md) file for details. 93 | 94 | ## Authors & Contributors 95 | 96 | - Artem Chistyakov 97 | - Petyo Ivanov 98 | - Ilya Sabanin 99 | - Hristo Deshev 100 | - Randy Schmidt 101 | - Chris Williams 102 | - Nicolás Sanguinetti 103 | - Laust Rud Jacobsen (rud) 104 | 105 | ## Issues & Comments 106 | 107 | Feel free to contact us if you encounter any issues with the library or Postmark API. 108 | Please leave all comments, bugs, requests and issues on the Issues page. 109 | 110 | ## License 111 | 112 | The Postmark Rails gem is licensed under the [MIT](http://www.opensource.org/licenses/mit-license.php) license. 113 | Refer to the [LICENSE](https://github.com/ActiveCampaign/postmark-rails/blob/main/LICENSE) file for more information. 114 | 115 | ## Copyright 116 | 117 | Copyright © 2022 ActiveCampaign LLC. 118 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | New versions of the gem are cut by the Postmark team, this is a quick guide to ensuring a smooth release. 2 | 3 | 1. Determine the next version of the gem by following the [SemVer](https://semver.org/) guidelines. 4 | 2. Verify all builds are passing on CircleCI for your branch. 5 | 3. Merge in your branch to main. 6 | 4. Update `lib/postmark-rails/version.rb` with the new version. 7 | 5. Update `CHANGELOG.rdoc` with a brief description of the changes. 8 | 6. Commit to git with a comment of "Bump version to x.y.z". 9 | 7. run `rake release` - This will push to github (with the version tag) and rubygems with the version in `lib/postmark-rails/version.rb`. 10 | *Note that if you're on Bundler 1.17 there's a bug that hides the prompt for your OTP. If it hangs after adding the tag then it's asking for your OTP, enter your OTP and press Enter. Bundler 2.x and beyond resolved this issue. * 11 | 8. Verify the new version is on [github](https://github.com/ActiveCampaign/postmark-rails) and [rubygems](https://rubygems.org/gems/postmark-rails). 12 | 9. Create a new release for the version on [Github releases](https://github.com/ActiveCampaign/postmark-rails/releases). 13 | 10. Add or update any related content to the [wiki](https://github.com/ActiveCampaign/postmark-rails/wiki). -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | Bundler::GemHelper.install_tasks 3 | require 'rake' 4 | 5 | require "rspec/core/rake_task" 6 | 7 | RSpec::Core::RakeTask.new(:spec) do |spec| 8 | spec.rspec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""] 9 | end 10 | 11 | task :default => :spec -------------------------------------------------------------------------------- /lib/postmark-rails.rb: -------------------------------------------------------------------------------- 1 | require 'active_support/rescuable' 2 | require 'action_mailer' 3 | require 'postmark' 4 | 5 | module PostmarkRails 6 | module ActionMailerExtensions 7 | def metadata 8 | @_message.metadata 9 | end 10 | 11 | def metadata=(val) 12 | @_message.metadata=(val) 13 | end 14 | end 15 | 16 | def self.install 17 | require 'postmark-rails/preview_interceptor' 18 | require 'postmark-rails/templated_mailer' 19 | ActionMailer::Base.add_delivery_method :postmark, Mail::Postmark 20 | ActionMailer::Base.send(:include, ActionMailerExtensions) 21 | end 22 | end 23 | 24 | if defined?(Rails) 25 | require 'postmark-rails/railtie' 26 | else 27 | PostmarkRails.install 28 | end 29 | -------------------------------------------------------------------------------- /lib/postmark-rails/preview_interceptor.rb: -------------------------------------------------------------------------------- 1 | module PostmarkRails 2 | class PreviewInterceptor 3 | def self.previewing_email(message) 4 | return unless message.templated? 5 | 6 | message.delivery_method(::Mail::Postmark, ::ActionMailer::Base.postmark_settings) 7 | message.prerender 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/postmark-rails/railtie.rb: -------------------------------------------------------------------------------- 1 | module PostmarkRails 2 | class Railtie < Rails::Railtie 3 | initializer 'postmark-rails', :before => 'action_mailer.set_configs' do 4 | ActiveSupport.on_load :action_mailer do 5 | PostmarkRails.install 6 | end 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/postmark-rails/templated_mailer.rb: -------------------------------------------------------------------------------- 1 | require 'active_support/hash_with_indifferent_access' 2 | 3 | module PostmarkRails 4 | module TemplatedMailerMixin 5 | READ_ONLY_HEADERS = %w(body content_type subject).freeze 6 | BODY_STUB = 'Temporary Postmark Template Body'.freeze 7 | SUBJECT_STUB = 'Temporary Postmark Template Subject'.freeze 8 | ALIAS_STUB = proc { action_name } 9 | 10 | def self.included(mailer) 11 | mailer.default( 12 | :body => BODY_STUB, 13 | :content_type => 'text/plain', 14 | :subject => SUBJECT_STUB, 15 | :postmark_template_alias => ALIAS_STUB 16 | ) 17 | mailer.extend(ClassMethods) 18 | end 19 | 20 | def template_model(*args) 21 | message.template_model(*args) 22 | end 23 | 24 | def template_model=(model) 25 | message.template_model = model 26 | end 27 | 28 | def mail(headers = {}) 29 | super(self.class.safe_headers(headers)) 30 | ensure 31 | message.body = standard_template_body 32 | message.subject = standard_template_subject 33 | end 34 | 35 | private 36 | 37 | module ClassMethods 38 | def default(headers = {}) 39 | super(safe_headers(headers)) 40 | end 41 | 42 | def safe_headers(headers = {}) 43 | headers = ActiveSupport::HashWithIndifferentAccess.new(headers) 44 | violation = READ_ONLY_HEADERS.find { |h| headers.key?(h) } 45 | raise ArgumentError, "Overriding '#{violation}' header in a templated mailer is not allowed." if violation 46 | headers 47 | end 48 | end 49 | 50 | def standard_template_body 51 | "This message is using a Postmark template.\n\n" \ 52 | "Alias: #{message.template_alias.inspect}\n" \ 53 | "Model:\n#{JSON.pretty_generate(message.template_model || {})}\n\n" \ 54 | 'Use the #prerender method on this object to contact the Postmark API ' \ 55 | "to pre-render the template.\n\n" \ 56 | "Cheers,\n" \ 57 | 'Your friends at Postmark' 58 | end 59 | 60 | def standard_template_subject 61 | "Postmark Template: #{message.template_alias.inspect}" 62 | end 63 | end 64 | 65 | class TemplatedMailer < ::ActionMailer::Base 66 | include TemplatedMailerMixin 67 | end 68 | end 69 | -------------------------------------------------------------------------------- /lib/postmark-rails/version.rb: -------------------------------------------------------------------------------- 1 | module PostmarkRails 2 | VERSION = '0.22.1' 3 | end 4 | -------------------------------------------------------------------------------- /postmark-rails.gemspec: -------------------------------------------------------------------------------- 1 | $:.push File.expand_path("../lib", __FILE__) 2 | require "postmark-rails/version" 3 | 4 | Gem::Specification.new do |s| 5 | s.name = %q{postmark-rails} 6 | s.version = PostmarkRails::VERSION 7 | s.authors = ["Petyo Ivanov", "Ilya Sabanin", "Artem Chistyakov"] 8 | s.description = %q{The Postmark Rails Gem is a drop-in plug-in for ActionMailer to send emails via Postmark, an email delivery service for web apps.} 9 | s.homepage = %q{https://postmarkapp.com} 10 | s.summary = %q{Postmark adapter for ActionMailer} 11 | 12 | s.metadata = { 13 | "source_code_uri" => "https://github.com/ActiveCampaign/postmark-rails" 14 | } 15 | 16 | s.extra_rdoc_files = [ 17 | "LICENSE", 18 | "README.md" 19 | ] 20 | s.rdoc_options = ["--charset=UTF-8"] 21 | 22 | s.add_dependency('actionmailer', ">= 3.0.0") 23 | s.add_dependency('postmark', '>= 1.21.3', '< 2.0') 24 | 25 | s.add_development_dependency("rake") 26 | 27 | s.files = `git ls-files`.split("\n") 28 | s.test_files = `git ls-files -- spec/*`.split("\n") 29 | s.require_paths = ["lib"] 30 | end 31 | -------------------------------------------------------------------------------- /postmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ActiveCampaign/postmark-rails/f9e4accd3a808c9d6e7f2115103723e1992f6fa4/postmark.png -------------------------------------------------------------------------------- /spec/fixtures/empty.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ActiveCampaign/postmark-rails/f9e4accd3a808c9d6e7f2115103723e1992f6fa4/spec/fixtures/empty.gif -------------------------------------------------------------------------------- /spec/fixtures/models/test_mailer.rb: -------------------------------------------------------------------------------- 1 | class TestMailer < ActionMailer::Base 2 | default :subject => 'hello', 3 | :to => 'sheldon@bigbangtheory.com', 4 | :from => 'leonard@bigbangtheory.com' 5 | 6 | def simple_message 7 | mail 8 | end 9 | 10 | def tagged_message 11 | mail(:tag => 'delivery') 12 | end 13 | 14 | def tracked_message 15 | mail(:track_opens => "true") 16 | end 17 | 18 | def multipart_message 19 | mail(:subject => "Your invitation to join Mixlr.") do |format| 20 | format.text 21 | format.html 22 | end 23 | end 24 | 25 | def message_with_attachment 26 | attachments['empty.gif'] = File.read(image_file) 27 | mail(:subject => "Message with attachment.") 28 | end 29 | 30 | def message_with_inline_image 31 | attachments.inline['empty.gif'] = File.read(image_file) 32 | mail(:subject => "Message with inline image.") 33 | end 34 | 35 | def message_with_metadata 36 | metadata['foo'] = 'bar' 37 | mail(:subject => 'Message with metadata.') 38 | end 39 | 40 | protected 41 | 42 | def image_file 43 | File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'empty.gif') 44 | end 45 | 46 | end -------------------------------------------------------------------------------- /spec/fixtures/views/test_mailer/message_with_attachment.erb: -------------------------------------------------------------------------------- 1 | attachments? -------------------------------------------------------------------------------- /spec/fixtures/views/test_mailer/message_with_inline_image.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | postmark 7 | 8 | -------------------------------------------------------------------------------- /spec/fixtures/views/test_mailer/message_with_metadata.text.erb: -------------------------------------------------------------------------------- 1 | This is a message with metadata. 2 | -------------------------------------------------------------------------------- /spec/fixtures/views/test_mailer/multipart_message.html.erb: -------------------------------------------------------------------------------- 1 | hello 2 | -------------------------------------------------------------------------------- /spec/fixtures/views/test_mailer/multipart_message.text.erb: -------------------------------------------------------------------------------- 1 | hello 2 | -------------------------------------------------------------------------------- /spec/fixtures/views/test_mailer/simple_message.erb: -------------------------------------------------------------------------------- 1 | hello 2 | -------------------------------------------------------------------------------- /spec/fixtures/views/test_mailer/tagged_message.erb: -------------------------------------------------------------------------------- 1 | test 2 | -------------------------------------------------------------------------------- /spec/fixtures/views/test_mailer/tracked_message.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

HELLO!

7 | 8 | -------------------------------------------------------------------------------- /spec/integration/batch_delivery_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'Delivering emails in batches' do 4 | let(:api_client) { Postmark::ApiClient.new('POSTMARK_API_TEST') } 5 | let(:messages) { [TestMailer.simple_message, 6 | TestMailer.tagged_message, 7 | TestMailer.multipart_message, 8 | TestMailer.message_with_attachment] } 9 | 10 | it 'delivers messages in batches' do 11 | expect { api_client.deliver_messages(messages) }. 12 | to change{messages.all? { |m| m.delivered?} }.to true 13 | end 14 | end -------------------------------------------------------------------------------- /spec/integration/delivery_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "Delivering messages with postmark-rails" do 4 | let(:api_token) { 'POSTMARK_API_TEST' } 5 | 6 | before do 7 | ActionMailer::Base.postmark_settings = { :api_token => api_token } 8 | end 9 | 10 | it 'delivers a simple message' do 11 | message = TestMailer.simple_message 12 | 13 | expect { message.deliver }.to change{message.delivered?}.to(true) 14 | end 15 | 16 | it 'delivers a tagged message' do 17 | message = TestMailer.tagged_message 18 | 19 | expect { message.deliver }.to change{message.delivered?}.to(true) 20 | end 21 | 22 | it 'delivers a multipart message' do 23 | message = TestMailer.multipart_message 24 | 25 | expect { message.deliver }.to change{message.delivered?}.to(true) 26 | end 27 | 28 | it 'delivers a message with attachments' do 29 | message = TestMailer.message_with_attachment 30 | request = message.to_postmark_hash 31 | 32 | expect(request['Attachments'].count).not_to be_zero 33 | expect { message.deliver }.to change{message.delivered?}.to(true) 34 | end 35 | 36 | it 'delivers a message with inline image' do 37 | message = TestMailer.message_with_inline_image 38 | request = message.to_postmark_hash 39 | 40 | expect(request['Attachments'].count).not_to be_zero 41 | expect(request['Attachments'].first).to have_key('ContentID') 42 | expect { message.deliver }.to change{message.delivered?}.to(true) 43 | end 44 | 45 | it 'delivers a message with metadata' do 46 | message = TestMailer.message_with_metadata 47 | 48 | request = message.to_postmark_hash 49 | 50 | expect(request['Metadata']).to eq('foo' => 'bar') 51 | expect { message.deliver }.to change { message.delivered? }.to true 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /spec/spec.opts: -------------------------------------------------------------------------------- 1 | --colour 2 | --format documentation 3 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift(File.dirname(__FILE__)) 2 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) 3 | 4 | require 'rubygems' 5 | require 'postmark' 6 | require 'postmark-rails' 7 | require 'json' 8 | 9 | ActionMailer::Base.delivery_method = :postmark 10 | ActionMailer::Base.prepend_view_path(File.join(File.dirname(__FILE__), "fixtures", "views")) 11 | 12 | Dir["#{File.dirname(__FILE__)}/fixtures/models/*.rb"].each { |f| require f } 13 | 14 | RSpec.configure do |config| 15 | def make_mailer(base, &block) 16 | mailer = Class.new(base, &block) 17 | @mailer_number = 0 18 | stub_const("Mailer#{@mailer_number += 1}", mailer) 19 | mailer 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/unit/postmark-rails_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "PostmarkRails3" do 4 | let!(:api_client) { Postmark::ApiClient.new('api-token') } 5 | 6 | def deliver(message) 7 | if message.respond_to?(:deliver_now) 8 | message.deliver_now 9 | else 10 | message.deliver 11 | end 12 | end 13 | 14 | it 'should allow setting an api token' do 15 | ActionMailer::Base.postmark_settings = {:api_token => 'api-token'} 16 | expect(ActionMailer::Base.postmark_settings[:api_token]).to eq('api-token') 17 | end 18 | 19 | it "should use postmark for delivery" do 20 | expect(Postmark::ApiClient).to receive(:new) { api_client } 21 | expect(api_client).to receive(:deliver_message) do |message| 22 | expect(message.subject).to eq("hello") 23 | end 24 | deliver(TestMailer.simple_message) 25 | end 26 | 27 | it "should allow tagging of message" do 28 | expect(Postmark::ApiClient).to receive(:new) { api_client } 29 | expect(api_client).to receive(:deliver_message) do |message| 30 | expect(message.tag.to_s).to eq("delivery") 31 | end 32 | deliver(TestMailer.tagged_message) 33 | end 34 | 35 | it "allows to enable open tracking" do 36 | expect(Postmark::ApiClient).to receive(:new) { api_client } 37 | expect(api_client).to receive(:deliver_message) do |message| 38 | expect(message.track_opens).to be_truthy 39 | expect(message.to_postmark_hash['TrackOpens']).to be true 40 | end 41 | deliver(TestMailer.tracked_message) 42 | end 43 | 44 | it "should work with multipart messages" do 45 | expect(Postmark::ApiClient).to receive(:new) { api_client } 46 | expect(api_client).to receive(:deliver_message) do |message| 47 | expect(message).to be_multipart 48 | expect(message.body_text.strip).to eq("hello") 49 | expect(message.body_html.strip).to eq("hello") 50 | end 51 | deliver(TestMailer.multipart_message) 52 | end 53 | 54 | it 'should work with messages containing attachments' do 55 | expect(Postmark::ApiClient).to receive(:new) { api_client } 56 | expect(api_client).to receive(:deliver_message) do |message| 57 | expect(message).to have_attachments 58 | end 59 | deliver(TestMailer.message_with_attachment) 60 | end 61 | end -------------------------------------------------------------------------------- /spec/unit/preview_interceptor_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | RSpec.describe PostmarkRails::PreviewInterceptor do 4 | describe '.previewing_email' do 5 | subject(:preview) { described_class.previewing_email(message) } 6 | let(:settings) { { :api_token => 'secret' } } 7 | 8 | before do 9 | ActionMailer::Base.postmark_settings = settings 10 | end 11 | 12 | context 'when given a templated message' do 13 | let(:message) do 14 | Mail::Message.new do 15 | template_alias 'foo' 16 | end 17 | end 18 | 19 | it 'changes the message' do 20 | message.freeze 21 | expect { preview }.to raise_error(StandardError, /can't modify/) 22 | end 23 | 24 | it 'changes delivery method to Postmark and prerenders' do 25 | expect(message).to receive(:prerender).exactly(1) 26 | expect { preview }.to change { message.delivery_method }.to(Mail::Postmark) 27 | expect(message.delivery_method.settings).to eq(settings) 28 | end 29 | end 30 | 31 | context 'when given a non-templated message' do 32 | let(:message) { Mail::Message.new } 33 | 34 | it 'returns the message "as is"' do 35 | message.freeze 36 | expect { preview }.to_not raise_error 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /spec/unit/templated_mailer_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | RSpec.describe PostmarkRails::TemplatedMailer do 4 | subject(:message) { mailer.test_message } 5 | 6 | shared_examples_for 'templated message' do |template_alias, model| 7 | it { is_expected.to be_templated } 8 | specify { expect(message.template_alias).to eq(template_alias) } 9 | specify { expect(message.template_model).to eq model } 10 | specify { expect(message.subject).to eq "Postmark Template: #{template_alias.inspect}" } 11 | specify { expect(message.body_text).to include(template_alias.inspect) } 12 | specify { expect(message.body_text).to include(JSON.pretty_generate(model || {})) } 13 | end 14 | 15 | context 'when template is not specified' do 16 | let(:mailer) do 17 | make_mailer(described_class) do 18 | def test_message 19 | mail :from => 'sender@postmarkapp.com', :to => 'recipient@postmarkapp.com' 20 | end 21 | end 22 | end 23 | 24 | it_behaves_like 'templated message', 'test_message' 25 | end 26 | 27 | context 'when template is specified' do 28 | let(:mailer) do 29 | make_mailer(described_class) do 30 | def test_message 31 | mail :from => 'sender@postmarkapp.com', 32 | :to => 'recipient@postmarkapp.com', 33 | :postmark_template_alias => 'custom_template' 34 | end 35 | end 36 | end 37 | 38 | it_behaves_like 'templated message', 'custom_template' 39 | end 40 | 41 | context 'when template model is specified' do 42 | let(:mailer) do 43 | make_mailer(described_class) do 44 | def test_message 45 | self.template_model = { :foo => 'bar' } 46 | mail :from => 'sender@postmarkapp.com', 47 | :to => 'recipient@postmarkapp.com' 48 | end 49 | end 50 | end 51 | 52 | it_behaves_like 'templated message', 'test_message', :foo => 'bar' 53 | end 54 | 55 | describe '.default' do 56 | it 'protects sensitive default headers from being overwritten' do 57 | %w(subject body content_type).each do |header| 58 | expect { described_class.default(header => 'foo') }. 59 | to raise_error(ArgumentError, "Overriding '#{header}' header in a templated mailer is not allowed.") 60 | end 61 | end 62 | end 63 | 64 | describe '#mail' do 65 | context "when overriding subject" do 66 | let(:mailer) do 67 | make_mailer(described_class) do 68 | def test_message 69 | mail :subject => 'Subject' 70 | end 71 | end 72 | end 73 | 74 | it 'protects it from being overwritten' do 75 | expect { mailer.test_message.subject }. 76 | to raise_error(ArgumentError, "Overriding 'subject' header in a templated mailer is not allowed.") 77 | end 78 | end 79 | 80 | context "when overriding body" do 81 | let(:mailer) do 82 | make_mailer(described_class) do 83 | def test_message 84 | mail :body => 'body' 85 | end 86 | end 87 | end 88 | 89 | it 'protects it from being overwritten' do 90 | expect { mailer.test_message.body }. 91 | to raise_error(ArgumentError, "Overriding 'body' header in a templated mailer is not allowed.") 92 | end 93 | end 94 | 95 | context "when overriding content_type" do 96 | let(:mailer) do 97 | make_mailer(described_class) do 98 | def test_message 99 | mail :content_type => 'content_type' 100 | end 101 | end 102 | end 103 | 104 | it 'protects it from being overwritten' do 105 | expect { mailer.test_message.content_type }. 106 | to raise_error(ArgumentError, "Overriding 'content_type' header in a templated mailer is not allowed.") 107 | end 108 | end 109 | end 110 | end 111 | --------------------------------------------------------------------------------