Git Product home page Git Product logo

mail-notify's Introduction

Build status Coverage status Gem Version Rails integration tests License

mail-notify

Rails plugin for GOV.UK Notify.

Great products and services like yours use mail-notify!

Installation

Add this line to your application's Gemfile:

gem 'mail-notify'

And then execute:

$ bundle

Configuration

Configure in each environment config/environments/*.rb (where * is test, development, production or whatever other environment(s) you have) file(s):

config.action_mailer.delivery_method = :notify
config.action_mailer.notify_settings = {
  api_key: YOUR_NOTIFY_API_KEY
}

We recommend using separate Notify 'test' API keys (email will not be sent but can be seen in Notify) in all environments except production so you can confirm the integration and generate previews without actually sending any email.

If you're using a different Notify service to GOV.UK Notify (for example GOV.CA Notify), you can also specify the Base URL in your setup:

config.action_mailer.delivery_method = :notify
config.action_mailer.notify_settings = {
  api_key: YOUR_NOTIFY_API_KEY,
  base_url: 'https://api.notification.alpha.canada.ca'
}

Mailers

There are two options for using mail-notify, manage the content in Notify with template mailers or in Rails with view mailers you can mix the two approaches as you need.

Whichever you choose, you'll need your mailers to inherit from Mail::Notify::Mailer like so:

class MyCustomMailer < Mail::Notify::Mailer
end

We recommend going 'all in' with Notify and having ApplicationMailer inherit for mail-notify:

class ApplicationMailer < Mail::Notify::Mailer
end

then have each mailer inherit from ApplicationMailer:

class MyCustomMailer < ApplicationMailer
end

Template mailers

Template mailers only require the template ID from Notify and an to email address, all of the content for the email is managed in Notify:

class MyCustomMailer < ApplicationMailer
    def welcome_email
        to = params[:to]

        template_mail("NOTIFY_TEMPLATE_ID", to: to)
    end
end

# call the template mailer
MyCustomMailer.with(to: "[email protected]").welcome_email.deliver_now!

You can add any number of personalisations to template mailers:

class MyCustomMailer < ApplicationMailer
    def appointment_email
        to = params[:to]
        name = params[:name]
        appointment_date = params[:appointment_date]

        template_mail(
            "NOTIFY_TEMPLATE_ID", 
            to: to,
            personalisation: {
                name: name,
                appointment_date: date.to_s
            }
        )
    end
end

# call the template mailer with personalisation options
MyCustomMailer.with(
    to: "[email protected]", 
    name: "First Last", 
    appointment_date: Date.new(2024, 01, 01)
).appointment_email.deliver_now!

A note on blank personalisation; The Notify API will not allow nil personalisation, if you expect nil values, you can wrap them in blank_allowed which converts them to an empty string:

MyCustomMailer.with(
    to: "[email protected]", name: blank_allowed(user.name)).welcome_email.deliver_now!

Or use params as the examples above.

View mailers

View mailers let you manage the content of emails with a Rails text view, with Notify's markdown like formatting supported.

You will still require a template in Notify, the template must be setup with subject and body personalisations, which will be replaced with those from your mailer and view:

Screenshot of a view mailer template in Notify

Your view mailer is then setup like this:

class MyCustomMailer < ApplicationMailer
    def welcome_email
        to = params[:to]
        subject= params[:subject]

        view_mail("NOTIFY_TEMPLATE_ID", to: to, subject: subject)
    end

With a subject being required.

Add the view named appropriately and in the conventional location:

app/views/my_custom_mailer/welcome_email.text.erb

Add content to the view:

Dear <%= @user.name %>

# Welcome to the service.

Here are some points to note:

* point one
* point two
* point three

^ Don't forget this.

Then call the mailer as usual:

MyCustomMailer.with(
    to: "[email protected]", 
    subject: "Welcome to service"
).welcome_email.deliver_now!

Only plain text views can be used, with the Notify markdown like formatting options. The email is sent as both HTML and plain text by Notify.

With optional Notify arguments

It's possible to pass two optional arguments to Notify with either template or view mailers.

  • reply_to_id: This is an email reply-to address specified by you to receive replies from your users
  • reference: A unique identifier you can create if necessary. This reference identifies a single unique notification or a batch of notifications

More information can be found in the Notify docs

class MyCustomMailer < ApplicationMailer
    def welcome_email
        to = params[:to]
        reference = params[:reference]
        reply_to_id = params[:reply_to_id]

        template_mail("NOTIFY_TEMPLATE_ID", to: to, reply_to_id: reply_to_id, reference: reference)
    end
end

# call the mailer
MyCustomMailer.with(
        to: "[email protected]", 
        reference: "YOUR_REFERENCE",
        reply_to_id: "YOUR_REPLY_TO"
    ).welcome_email.deliver_now!

Previews

Rails previews are supported.

The Rails delivery method must be set to :notify and a Notify API key will be required for previews to work as the preview is generated by the Notify API.

With Devise

Mail-notify is compatible with anything that uses ActionMailer, Devise is a popular authentication gem that uses ActionMailer to send emails relating to accounts, see instructions in the wiki for more details of using mail-notify with Devise.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run bin/rspec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To release a new version, update the version number in version.rb, and then tag the commit on main - the release will be built and published by the publish.yml GitHub action.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/dxw/mail-notify. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the Mail::Notify project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

mail-notify's People

Contributors

broisatse avatar cristinaro avatar dependabot[bot] avatar dragon-dxw avatar dxw-rails-user avatar em-cd avatar erbridge avatar ethanmills avatar jacksonj04 avatar mec avatar pezholio avatar pixeltrix avatar renovate[bot] avatar robbiepaul avatar tahb avatar tekin avatar tijmenb avatar userman123 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mail-notify's Issues

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Ignored or Blocked

These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.

Detected dependencies

bundler
Gemfile
github-actions
.github/workflows/build.yml
  • actions/checkout v4
  • ruby/setup-ruby v1
.github/workflows/publish.yml
  • actions/checkout v4
  • ruby/setup-ruby v1
ruby-version
.ruby-version
  • ruby 2.7.8
spec/dummy/.ruby-version
  • ruby 3.2.2

  • Check this box to trigger a request for Renovate to run again on this repository

Version 1.0.5 triggers uninitialized constant Mail::Notify error

The build on our repo is failing on the dependabot PR for the update from 1.0.4.to 1.0.5 DFE-Digital/claim-additional-payments-for-teaching#2131. I will investigate further but I think you should be aware of this as it's a minor version and shouldn't be breaking things.

Spec error:

NameError:
  uninitialized constant Mail::Notify
# ./app/mailers/application_mailer.rb:1:in `<top (required)>'

Affected class:

class ApplicationMailer < Mail::Notify::Mailer

[Feature request] Allow setting multiple API keys

Some of our projects use multiple Notify services, requiring different API keys. The mail-notify gem doesn't seem to be supporting changing the API key as it reads it directly from ActionMailer. I solved this by updating the ActionMailer settings just before calling the view_mail method. This is not a very elegant solution and could potentially cause issues with parallel executions. Example here: https://github.com/DFE-Digital/refer-serious-misconduct/blob/main/app/mailers/application_mailer.rb Please let me know if there is a better way of making this work or if there are any plans to update the gem for this use case.

Previews not supported in Rails > 7.0.8

Rails 7.1 introduces a change to the email preview template that means our test suite fails.

We've temporarilly pinned Rails to 7.0.8 to give us space to fix the underlying issue, which probably means updating the test app to 7.1.2.

We want to move carefully on Mail Notify as a number of our own and other project depend on it.

Ideally we will maintain support for as many versions of Ruby and Rails as we can, which means it's often not just a case of updating Rails (or any dependency) without considering the wider consquences.

Add support for previews

At the moment, using ActionMailer::Preview generates a plaintext preview with the markdown that is used by Notify. It would be nice to use Notify's built in preview functionality to process the Markdown via Notify's servers and display exactly what the user would see.

This might involve extending (or at least examining the internals of) the Rails Mailers Controller which displays the final mailer to the user.

Missing instructions for integration with devise

Context: Tried following the current README and kept hitting an error of undefined method view_mail. The intent was using notify for sending emails of password resets.

After checking the repo of the owner that suggested the readme update for the devise integration, I found these two extra settings were needed to get this to work.

Couldn't submit a PR to update the README so here is the instruction update:

With Devise

If you're using Devise, you can overwrite your Devise mailer to use mail-notify for password reset emails etc.

In app/mailers/application_mailer.rb ensure your application mailer inherits from Mail::Notify

class ApplicationMailer < Mail::Notify::Mailer
end

In config/initializers/devise.rb:

config.mailer = 'DeviseMailer'
config.parent_mailer = 'ApplicationMailer'

in app/mailers/devise_mailer.rb:

class DeviseMailer < Devise::Mailer
  def devise_mail(record, action, opts = {}, &block)
    initialize_from_record(record)
    view_mail(ENV['NOTIFY_TEMPLATE_ID'], headers_for(action, opts))
  end
end

ERROR 'Missing personalisation: body'

Hey @pezholio πŸ‘‹

Started testing gem - Quite useful tool πŸ‘

But on attempt to try send email from my view as body (instead of notify template) I'm getting error:

TestMailer.welcome("my_real_email_here").deliver!

  Rendering test_mailer/welcome.html.slim within layouts/mailer
  Rendered test_mailer/welcome.html.slim within layouts/mailer (6.9ms)
  Rendering test_mailer/welcome.text.slim
  Rendered test_mailer/welcome.text.slim (3.2ms)
TestMailer#welcome: processed outbound mail in 1103.4ms
Traceback (most recent call last):
        1: from (irb):1
Notifications::Client::BadRequestError (400 [{"error"=>"BadRequestError", "message"=>"Missing personalisation: body"}])

MY STEPS:

1) I prepared proper Email template

Attached screenshot:

template

In a code I have:

2) Gemfile

gem 'rails', '~> 5.2'
gem 'mail-notify'

in Gemfile.lock I see:

actionmailer (5.2.2.1)
      actionpack (= 5.2.2.1)
      actionview (= 5.2.2.1)
      activejob (= 5.2.2.1)
      mail (~> 2.5, >= 2.5.4)
      rails-dom-testing (~> 2.0)

mail-notify (0.0.3)
      actionmailer (~> 5.0)
      notifications-ruby-client (~> 2.0)

notifications-ruby-client (2.10.0)
      jwt (>= 1.5, < 3)

3) config/environments/development.rb

config.action_mailer.delivery_method = :notify
config.action_mailer.notify_settings = {
    api_key: ENV['GOV_UK_NOTIFY_API_KEY']
}

4) .env

GOV_UK_NOTIFY_API_KEY=KEY
GOV_UK_NOTIFY_API_TEMPLATE_ID=ID

5) app/mailers/application_mailer.rb

class ApplicationMailer < Mail::Notify::Mailer
  default from: "[email protected]",
              reply_to: "[email protected]"

  layout "mailer"
end

6) app/mailers/test_mailer.rb

class TestMailer < ApplicationMailer
  def welcome(email)
    @email = email
    @subject = "Test mailer!"

    view_mail ENV['GOV_UK_NOTIFY_API_TEMPLATE_ID'], to: @email, subject: @subject
  end
end

7) app/views/test_mailer/welcome.html.slim

p
  ' Hi BRO,

p
  | It's just test

8) app/views/test_mailer/welcome.text.slim

| Hi BRO,

| It's just test

9) app/views/layouts/mailer.html.slim

html
head
  meta content="text/html;charset=utf-8" http-equiv="Content-Type"
  meta content="utf-8" http-equiv="encoding"
  / This disables auto detection of phone numbers in some clients. Remove if not needed.
  / meta name="format-detection" content="telephone=no"
  title = content_for?(:title) ? yield(:title) : "TEST"

body style="font-family: Helvetica, Arial, sans-serif; font-size: 16px; margin: 0; color: #0b0c0c;" data-force-encoding="βœ“"
  table width="100%" cellpadding="0" cellspacing="0" border="0"
    tr
      td width="100%" height="53px" bgcolor="#0b0c0c"
        table width="580" cellpadding="0" cellspacing="0" border="0" align="center"
          tr
            td width="100%" bgcolor="#0b0c0c" valign="middle"
              / This asset should be hosted by the service
              = image_tag "govuk_logotype_email.png", alt: "GOV.UK", border: "0"
    tr
      td width="100%" height="53px"
        table width="580" cellpadding="0" cellspacing="0" border="0" align="center"
          tr
            td width="100%" valign="middle" style="font-size: 19px;"
              / This asset should be hosted by the service
              = image_tag "logo.png",
                          alt: "Test",
                          border: "0",
                          style: "margin-right: 10px; padding-left: 5px; border-left: 2px solid #005ea5; vertical-align: text-bottom;"
              ' The TEST app

  table width="100%" cellpadding="0" cellspacing="0" border="0" bgcolor="#FFFFFF" style="margin-bottom: 19px;"
    tr
      td width="100%"
        table width="580" cellpadding="0" cellspacing="0" border="0" align="center"
          tr
            td width="75%"
              = yield
          td width="25%" &nbsp;

NOTE:

I also was trying to use notify_mail method instead of view_mail, for example:

class TestMailer < ApplicationMailer
  def welcome(email)
    @email = email
    @subject = "Test mailer!"

    notify_mail ENV['GOV_UK_NOTIFY_API_TEMPLATE_ID'], to: @email, subject: @subject
  end
end

But in this case it raising issue:

TestMailer.welcome("my_real_email_here").deliver!

TestMailer#welcome: processed outbound mail in 12.7ms
Traceback (most recent call last):
        2: from (irb):3
        1: from app/mailers/test_mailer.rb:6:in `welcome'
NoMethodError (undefined method `notify_mail' for #<TestMailer:0x000055b99e62fd38>
Did you mean?  notify_settings)

I re-checked README multiple times - but still not able to find out what I missed 😭

Appreciate any help on it 🍻

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Location: renovate.json
Error type: Invalid JSON (parsing failed)
Message: Syntax error: expecting end of expression or separator near se
"igno

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.