Merge branch 'develop' into unstable

This commit is contained in:
Luca Guidi 2020-10-19 09:40:38 +02:00
commit 3a14b64015
No known key found for this signature in database
GPG Key ID: 4F9DE2097876665B
19 changed files with 214 additions and 128 deletions

View File

@ -4,10 +4,10 @@
#
version: 2
jobs:
"ruby-2.5":
"ruby-2.6":
docker:
- image: hanami/ruby-2.5
working_directory: ~/hanami-utils
- image: hanami/ruby-2.6
working_directory: ~/hanami-mailer
steps:
- checkout
# Download and cache dependencies
@ -29,10 +29,10 @@ jobs:
name: run tests
command: |
./script/ci
"ruby-2.6":
"ruby-2.7":
docker:
- image: hanami/ruby-2.6
working_directory: ~/hanami-utils
- image: hanami/ruby-2.7
working_directory: ~/hanami-mailer
steps:
- checkout
# Download and cache dependencies
@ -59,5 +59,5 @@ workflows:
version: 2
build:
jobs:
- "ruby-2.5"
- "ruby-2.6"
- "ruby-2.7"

View File

@ -1,22 +0,0 @@
language: ruby
sudo: false
cache: bundler
before_script:
- gem update --system
script: ./script/ci
rvm:
- 2.5
- 2.6
- ruby-head
matrix:
allow_failures:
- rvm: ruby-head
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/fde2367248d53de4fe70
on_success: change # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: never # options: [always|never|change] default: always

View File

@ -1,9 +1,16 @@
# Hanami::Mailer
Mail for Ruby applications
<<<<<<< HEAD
## v2.0.0.alpha1 (unreleased)
### Changed
- [Luca Guidi] Drop support for Ruby: MRI 2.3, and 2.4.
=======
## v1.3.2 - 2020-02-03
### Added
- [Luca Guidi] Official support for Ruby: MRI 2.7
- [glaszig] Added `Hanami::Mailer.return_path` and `#return_path` to specify `MAIL FROM` address
>>>>>>> develop
## v1.3.1 - 2019-01-18
### Added

View File

@ -4,9 +4,8 @@ source "https://rubygems.org"
gemspec
unless ENV["CI"]
gem "byebug", require: false, platforms: :mri
gem "allocation_stats", require: false
gem "benchmark-ips", require: false
gem "byebug", require: false, platforms: :mri
gem "yard", require: false
end
gem "hanami-utils", "~> 2.0.alpha", require: false, git: "https://github.com/hanami/utils.git", branch: "unstable"

View File

@ -5,9 +5,8 @@ Mail for Ruby applications.
## Status
[![Gem Version](https://badge.fury.io/rb/hanami-mailer.svg)](https://badge.fury.io/rb/hanami-mailer)
[![TravisCI](https://travis-ci.org/hanami/mailer.svg?branch=master)](https://travis-ci.org/hanami/mailer)
[![CircleCI](https://circleci.com/gh/hanami/mailer/tree/master.svg?style=svg)](https://circleci.com/gh/hanami/mailer/tree/master)
[![Test Coverage](https://codecov.io/gh/hanami/mailer/branch/master/graph/badge.svg)](https://codecov.io/gh/hanami/mailer)
[![CircleCI](https://circleci.com/gh/hanami/mailer/tree/unstable.svg?style=svg)](https://circleci.com/gh/hanami/mailer/tree/unstable)
[![Test Coverage](https://codecov.io/gh/hanami/mailer/branch/unstable/graph/badge.svg)](https://codecov.io/gh/hanami/mailer)
[![Depfu](https://badges.depfu.com/badges/739c6e10eaf20d3ba4240d00828284db/overview.svg)](https://depfu.com/github/hanami/mailer?project=Bundler)
[![Inline Docs](http://inch-ci.org/github/hanami/mailer.svg)](http://inch-ci.org/github/hanami/mailer)
@ -22,7 +21,7 @@ Mail for Ruby applications.
## Rubies
__Hanami::Mailer__ supports Ruby (MRI) 2.5+
__Hanami::Mailer__ supports Ruby (MRI) 2.6+
## Installation
@ -128,6 +127,7 @@ configuration = Hanami::Mailer::Configuration.new do |config|
end
class WelcomeMailer < Hanami::Mailer
return_path 'bounce@sender.com'
from 'noreply@sender.com'
to 'noreply@recipient.com'
cc 'cc@sender.com'
@ -447,6 +447,6 @@ __Hanami::Mailer__ uses [Semantic Versioning 2.0.0](http://semver.org)
## Copyright
Copyright © 2015-2019 Luca Guidi Released under MIT License
Copyright © 2015-2020 Luca Guidi Released under MIT License
This project was formerly known as Lotus (`lotus-mailer`).

View File

@ -40,9 +40,9 @@ total_memsize = stats.allocations.bytes.to_a.inject(&:+)
puts "total memsize: #{total_memsize}"
detailed_allocations = stats.allocations(alias_paths: true)
.group_by(:sourcefile, :class_plus)
.sort_by_count
.to_text
.group_by(:sourcefile, :class_plus)
.sort_by_count
.to_text
puts "allocations by source file and class:"
puts detailed_allocations

View File

@ -15,17 +15,18 @@ Gem::Specification.new do |spec|
spec.homepage = "http://hanamirb.org"
spec.license = "MIT"
spec.files = `git ls-files -- lib/* CHANGELOG.md LICENSE.md README.md hanami-mailer.gemspec`.split($/) # rubocop:disable Style/SpecialGlobalVars
spec.files = `git ls-files -- lib/* CHANGELOG.md LICENSE.md README.md hanami-mailer.gemspec`.split($/)
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.required_ruby_version = ">= 2.5.0"
spec.required_ruby_version = ">= 2.6.0"
spec.add_dependency "hanami-utils", "~> 2.0.alpha"
spec.add_dependency "tilt", "~> 2.0", ">= 2.0.1"
spec.add_dependency "mail", "~> 2.6"
spec.add_development_dependency "bundler", ">= 1.6", "< 3"
spec.add_development_dependency "rake", "~> 12"
spec.add_development_dependency "rake", "~> 13"
spec.add_development_dependency "rspec", "~> 3.7"
spec.add_development_dependency "rubocop", "0.91"
end

View File

@ -77,6 +77,7 @@ module Hanami
# @since next
# @api unstable
def self.inherited(base)
super
@_subclasses.push(base)
base.extend Dsl
end
@ -168,15 +169,15 @@ module Hanami
# mailer.deliver(invoice: invoice, user: user, charset: 'iso-8859')
def deliver(locals)
mail(locals).deliver
rescue ArgumentError => e
raise MissingDeliveryDataError if e.message =~ /SMTP (From|To) address/
rescue ArgumentError => exception
raise MissingDeliveryDataError if exception.message =~ /SMTP (From|To) address/
raise
end
# @since next
# @api unstable
alias call deliver
alias_method :call, :deliver
# Render a single template with the specified format.
#
@ -208,17 +209,16 @@ module Hanami
# @api unstable
# @since next
#
# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/MethodLength
def bind(mail, locals)
def bind(mail, locals) # rubocop:disable Metrics/AbcSize
charset = locals.fetch(:charset, configuration.default_charset)
mail.from = __dsl(:from, locals)
mail.to = __dsl(:to, locals)
mail.cc = __dsl(:cc, locals)
mail.bcc = __dsl(:bcc, locals)
mail.reply_to = __dsl(:reply_to, locals)
mail.subject = __dsl(:subject, locals)
mail.return_path = __dsl(:return_path, locals)
mail.from = __dsl(:from, locals)
mail.to = __dsl(:to, locals)
mail.cc = __dsl(:cc, locals)
mail.bcc = __dsl(:bcc, locals)
mail.reply_to = __dsl(:reply_to, locals)
mail.subject = __dsl(:subject, locals)
mail.html_part = __part(:html, charset, locals)
mail.text_part = __part(:txt, charset, locals)
@ -226,8 +226,6 @@ module Hanami
mail.charset = charset
mail.delivery_method(*configuration.delivery_method)
end
# rubocop:enable Metrics/MethodLength
# rubocop:enable Metrics/AbcSize
# @since next
# @api unstable

View File

@ -1,5 +1,6 @@
# frozen_string_literal: true
require "set"
require "hanami/utils/kernel"
require "hanami/mailer/template_name"
require "hanami/mailer/templates_finder"
@ -154,7 +155,7 @@ module Hanami
@modules = []
end
alias unload! reset!
alias_method :unload!, :reset!
# Copy the configuration for the given mailer
#

View File

@ -15,14 +15,15 @@ module Hanami
# @api unstable
def self.extended(base)
base.class_eval do
@from = nil
@to = nil
@cc = nil
@bcc = nil
@reply_to = nil
@subject = nil
@template = nil
@before = ->(*) {}
@from = nil
@to = nil
@cc = nil
@bcc = nil
@reply_to = nil
@return_path = nil
@subject = nil
@template = nil
@before = ->(*) {}
end
end
@ -210,6 +211,73 @@ module Hanami
end
end
# Sets the bcc (blind carbon copy) for mail messages
#
# It accepts a hardcoded value as a string or array of strings.
# For dynamic values, you can specify a symbol that represents an instance
# method.
#
# This value is optional.
#
# When a value is given, it specifies the bcc for the email.
# When a value is not given, it returns the bcc of the email.
#
# This is part of a DSL, for this reason when this method is called with
# an argument, it will set the corresponding class variable. When
# called without, it will return the already set value, or the default.
#
# @overload bcc(value)
# Sets the bcc
# @param value [String, Array, Symbol] the hardcoded value or method name
# @return [NilClass]
#
# @overload bcc
# Returns the bcc
# @return [String, Array, Symbol] the recipient
#
# @since 0.3.0
#
# @example Hardcoded value (String)
# require 'hanami/mailer'
#
# class WelcomeMailer < Hanami::Mailer
# bcc "other.user@example.com"
# end
#
# @example Hardcoded value (Array)
# require 'hanami/mailer'
#
# class WelcomeMailer < Hanami::Mailer
# bcc ["other.user-1@example.com", "other.user-2@example.com"]
# end
#
# @example Lazy value (Proc)
# require 'hanami/mailer'
#
# class WelcomeMailer < Hanami::Mailer
# bcc ->(locals) { locals.fetch(:user).email }
# end
#
# user = User.new(name: 'L')
# WelcomeMailer.new(configuration: configuration).deliver(user: user)
#
# @example Lazy values (Proc)
# require 'hanami/mailer'
#
# class WelcomeMailer < Hanami::Mailer
# bcc ->(locals) { locals.fetch(:users).map(&:email) }
# end
#
# users = [User.new(name: 'L'), User.new(name: 'MG')]
# WelcomeMailer.new(configuration: configuration).deliver(users: users)
def bcc(value = nil)
if value.nil?
@bcc
else
@bcc = value
end
end
# Sets the reply_to for mail messages
#
# It accepts a hardcoded value as a string or array of strings.
@ -299,70 +367,60 @@ module Hanami
end
end
# Sets the bcc (blind carbon copy) for mail messages
# Sets the MAIL FROM address for mail messages.
# This lets you specify a "bounce address" different from the sender
# address specified with `from`.
#
# It accepts a hardcoded value as a string or array of strings.
# For dynamic values, you can specify a symbol that represents an instance
# method.
# It accepts a hardcoded value as a string, or a symbol that represents
# an instance method for more complex logic.
#
# This value is optional.
#
# When a value is given, it specifies the bcc for the email.
# When a value is not given, it returns the bcc of the email.
# When a value is given, specify the MAIL FROM address of the email
# Otherwise, it returns the MAIL FROM address of the email
#
# This is part of a DSL, for this reason when this method is called with
# an argument, it will set the corresponding class variable. When
# called without, it will return the already set value, or the default.
#
# @overload bcc(value)
# Sets the bcc
# @param value [String, Array, Symbol] the hardcoded value or method name
# @overload return_path(value)
# Sets the MAIL FROM address
# @param value [String, Symbol] the hardcoded value or method name
# @return [NilClass]
#
# @overload bcc
# Returns the bcc
# @return [String, Array, Symbol] the recipient
# @overload return_path
# Returns the MAIL FROM address
# @return [String, Symbol] the MAIL FROM address
#
# @since 0.3.0
# @since 1.3.2
#
# @example Hardcoded value (String)
# require 'hanami/mailer'
#
# class WelcomeMailer < Hanami::Mailer
# bcc "other.user@example.com"
# class WelcomeMailer
# include Hanami::Mailer
#
# return_path "bounce@example.com"
# end
#
# @example Hardcoded value (Array)
# @example Method (Symbol)
# require 'hanami/mailer'
#
# class WelcomeMailer < Hanami::Mailer
# bcc ["other.user-1@example.com", "other.user-2@example.com"]
# class WelcomeMailer
# include Hanami::Mailer
# return_path :bounce_address
#
# private
#
# def bounce_address
# "bounce@example.com"
# end
# end
#
# @example Lazy value (Proc)
# require 'hanami/mailer'
#
# class WelcomeMailer < Hanami::Mailer
# bcc ->(locals) { locals.fetch(:user).email }
# end
#
# user = User.new(name: 'L')
# WelcomeMailer.new(configuration: configuration).deliver(user: user)
#
# @example Lazy values (Proc)
# require 'hanami/mailer'
#
# class WelcomeMailer < Hanami::Mailer
# bcc ->(locals) { locals.fetch(:users).map(&:email) }
# end
#
# users = [User.new(name: 'L'), User.new(name: 'MG')]
# WelcomeMailer.new(configuration: configuration).deliver(users: users)
def bcc(value = nil)
def return_path(value = nil)
if value.nil?
@bcc
@return_path
else
@bcc = value
@return_path = value
end
end

View File

@ -11,8 +11,8 @@ module Hanami
#
# TODO this is identical to Hanami::View, consider to move into Hanami::Utils
class Template
def initialize(template)
@_template = Tilt.new(template)
def initialize(template, encoding = Encoding::UTF_8)
@_template = Tilt.new(template, default_encoding: encoding)
freeze
end

View File

@ -18,7 +18,7 @@ module Hanami
class << self
# @since next
# @api unstable
alias [] call
alias_method :[], :call
end
end
end

View File

@ -98,7 +98,10 @@ module Hanami
# @api unstable
# @since 0.1.0
def templates(template_name, lookup = search_path)
Utils::FileList["#{[root, lookup, template_name].join(separator)}#{format_separator}#{format}#{format_separator}#{engines}"]
root_path = [root, lookup, template_name].join(separator)
search_path = "#{format_separator}#{format}#{format_separator}#{engines}"
Utils::FileList["#{root_path}#{search_path}"]
end
# @api unstable

View File

@ -26,11 +26,11 @@ upload_code_coverage() {
}
main() {
prepare_build &&
print_ruby_version &&
run_code_quality_checks &&
run_unit_tests &&
upload_code_coverage
prepare_build
print_ruby_version
run_code_quality_checks
run_unit_tests
upload_code_coverage
}
main

View File

@ -120,7 +120,7 @@ RSpec.describe Hanami::Mailer do
subject { options.fetch(:deliveries).first }
let(:mailer) { WelcomeMailer.new(configuration: configuration) }
let(:options) { { deliveries: [] } }
let(:options) { {deliveries: []} }
let(:configuration) do
configuration = Hanami::Mailer::Configuration.new do |config|

View File

@ -62,11 +62,12 @@ class ProcMailer < Hanami::Mailer
end
class WelcomeMailer < Hanami::Mailer
from "noreply@sender.com"
to ["noreply@recipient.com", "owner@recipient.com"]
cc "cc@recipient.com"
bcc "bcc@recipient.com"
reply_to "reply_to@recipient.com"
from "noreply@sender.com"
to ["noreply@recipient.com", "owner@recipient.com"]
cc "cc@recipient.com"
bcc "bcc@recipient.com"
reply_to "reply_to@recipient.com"
return_path "bounce@sender.com"
subject "Welcome"

View File

@ -63,22 +63,22 @@ RSpec.describe Hanami::Mailer::Configuration do
describe "set with a symbol" do
before do
subject.delivery_method = :exim, { location: "/path/to/exim" }
subject.delivery_method = :exim, {location: "/path/to/exim"}
end
it "saves the delivery method in the configuration" do
expect(subject.delivery_method).to eq([:exim, { location: "/path/to/exim" }])
expect(subject.delivery_method).to eq([:exim, {location: "/path/to/exim"}])
end
end
describe "set with a class" do
before do
subject.delivery_method = MandrillDeliveryMethod,
{ username: "mandrill-username", password: "mandrill-api-key" }
{username: "mandrill-username", password: "mandrill-api-key"}
end
it "saves the delivery method in the configuration" do
expect(subject.delivery_method).to eq([MandrillDeliveryMethod, username: "mandrill-username", password: "mandrill-api-key"])
expect(subject.delivery_method).to eq([MandrillDeliveryMethod, {username: "mandrill-username", password: "mandrill-api-key"}])
end
end
end

View File

@ -76,6 +76,46 @@ RSpec.describe Hanami::Mailer::Dsl do
end
end
describe ".reply_to" do
it "returns the default value" do
expect(mailer.reply_to).to be(nil)
end
it "sets a single value" do
email_address = "reply@hanami.test"
mailer.reply_to email_address
expect(mailer.reply_to).to eq(email_address)
end
it "sets an array of values" do
email_addresses = ["bcc@hanami.test"]
mailer.reply_to email_addresses
expect(mailer.reply_to).to eq(email_addresses)
end
end
describe ".return_path" do
it "returns the default value" do
expect(mailer.return_path).to be(nil)
end
it "sets a single value" do
email_address = "return@hanami.test"
mailer.return_path email_address
expect(mailer.return_path).to eq(email_address)
end
it "sets an array of values" do
email_addresses = ["return@hanami.test"]
mailer.return_path email_addresses
expect(mailer.return_path).to eq(email_addresses)
end
end
describe ".subject" do
it "returns the default value" do
expect(mailer.subject).to be(nil)

View File

@ -151,7 +151,7 @@ RSpec.describe Hanami::Mailer do
describe "when locals are parsed in" do
let(:mailer) { RenderMailer.new(configuration: configuration) }
let(:locals) { { user: User.new("Luca") } }
let(:locals) { {user: User.new("Luca")} }
it "renders template with parsed locals" do
expect(mailer.render(:html, locals)).to include(locals.fetch(:user).name)
@ -160,7 +160,7 @@ RSpec.describe Hanami::Mailer do
describe "with HAML template engine" do
let(:mailer) { TemplateEngineMailer.new(configuration: configuration) }
let(:locals) { { user: User.new("MG") } }
let(:locals) { {user: User.new("MG")} }
it "renders template with parsed locals" do
expect(mailer.render(:html, locals)).to include(%(<h1>\n#{locals.fetch(:user).name}\n</h1>\n))