lib/backup/notifier/mail.rb
# frozen_string_literal: true
require "mail"
module Backup
module Notifier
class Mail < Base
##
# Mail delivery method to be used by the Mail gem.
#
# Supported methods:
#
# [:smtp - ::Mail::SMTP (default)]
# Settings used by this method:
# {#address}, {#port}, {#domain}, {#user_name}, {#password},
# {#authentication}, {#encryption}, {#openssl_verify_mode}
#
# [:sendmail - ::Mail::Sendmail]
# Settings used by this method:
# {#sendmail_args}
#
# [:exim - ::Mail::Exim]
# Settings used by this method:
# {#exim_args}
#
# [:file - ::Mail::FileDelivery]
# Settings used by this method:
# {#mail_folder}
#
attr_accessor :delivery_method
##
# Sender Email Address
attr_accessor :from
##
# Receiver Email Address
attr_accessor :to
##
# CC receiver Email Address
attr_accessor :cc
##
# BCC receiver Email Address
attr_accessor :bcc
##
# Set reply to email address
attr_accessor :reply_to
##
# SMTP Server Address
attr_accessor :address
##
# SMTP Server Port
attr_accessor :port
##
# Your domain (if applicable)
attr_accessor :domain
##
# SMTP Server Username (sender email's credentials)
attr_accessor :user_name
##
# SMTP Server Password (sender email's credentials)
attr_accessor :password
##
# Authentication type
#
# Acceptable values: +:plain+, +:login+, +:cram_md5+
attr_accessor :authentication
##
# Set the method of encryption to be used for the +SMTP+ connection.
#
# [:starttls (default)]
# Use +STARTTLS+ to upgrade the connection to a +SSL/TLS+ connection.
#
# [:tls or :ssl]
# Use a +SSL/TLS+ connection.
#
# [:none]
# No encryption will be used.
attr_accessor :encryption
##
# OpenSSL Verify Mode
#
# Valid modes: +:none+, +:peer+, +:client_once+, +:fail_if_no_peer_cert+
# See +OpenSSL::SSL+ for details.
#
# Use +:none+ for a self-signed and/or wildcard certificate
attr_accessor :openssl_verify_mode
##
# Optional arguments to pass to `sendmail`
#
# Note that this will override the defaults set by the Mail gem
# (currently: '-i'). So, if set here, be sure to set all the arguments
# you require.
#
# Example: '-i -X/tmp/traffic.log'
attr_accessor :sendmail_args
##
# Optional arguments to pass to `exim`
#
# Note that this will override the defaults set by the Mail gem
# (currently: '-i -t') So, if set here, be sure to set all the arguments
# you require.
#
# Example: '-i -t -X/tmp/traffic.log'
attr_accessor :exim_args
##
# Folder where mail will be kept when using the `:file` `delivery_method`.
#
# Default location is '$HOME/Backup/emails'
attr_accessor :mail_folder
##
# Array of statuses for which the log file should be attached.
#
# Available statuses are: `:success`, `:warning` and `:failure`.
# Default: [:warning, :failure]
attr_accessor :send_log_on
def initialize(model, &block)
super
instance_eval(&block) if block_given?
@send_log_on ||= [:warning, :failure]
@encryption ||= :starttls
end
private
##
# Notify the user of the backup operation results.
#
# `status` indicates one of the following:
#
# `:success`
# : The backup completed successfully.
# : Notification will be sent if `on_success` is `true`.
#
# `:warning`
# : The backup completed successfully, but warnings were logged.
# : Notification will be sent, including a copy of the current
# : backup log, if `on_warning` or `on_success` is `true`.
#
# `:failure`
# : The backup operation failed.
# : Notification will be sent, including a copy of the current
# : backup log, if `on_failure` is `true`.
#
def notify!(status)
email = new_email
email.subject = message.call(model, status: status_data_for(status))
send_log = send_log_on.include?(status)
template = Backup::Template.new(model: model, send_log: send_log)
email.body = template.result(sprintf("notifier/mail/%s.erb",
status.to_s))
if send_log
email.convert_to_multipart
email.attachments["#{model.time}.#{model.trigger}.log"] = {
mime_type: "text/plain;",
content: Logger.messages.map(&:formatted_lines).flatten.join("\n")
}
end
email.deliver! # raise error if unsuccessful
end
##
# Configures the Mail gem by setting the defaults.
# Creates and returns a new email, based on the @delivery_method used.
def new_email
method = %w[smtp sendmail exim file test]
.index(@delivery_method.to_s) ? @delivery_method.to_s : "smtp"
options =
case method
when "smtp"
opts = {
address: @address,
port: @port,
user_name: @user_name,
password: @password,
authentication: @authentication,
enable_starttls_auto: @encryption == :starttls,
openssl_verify_mode: @openssl_verify_mode,
ssl: @encryption == :ssl,
tls: @encryption == :tls
}
# Don't override default domain setting if domain not applicable.
# ref https://github.com/mikel/mail/blob/2.6.3/lib/mail/network/delivery_methods/smtp.rb#L82
opts[:domain] = @domain if @domain
opts
when "sendmail"
opts = {}
opts[:location] = utility(:sendmail)
opts[:arguments] = @sendmail_args if @sendmail_args
opts
when "exim"
opts = {}
opts[:location] = utility(:exim)
opts[:arguments] = @exim_args if @exim_args
opts
when "file"
@mail_folder ||= File.join(Config.root_path, "emails")
{ location: File.expand_path(@mail_folder) }
when "test" then {}
end
email = ::Mail.new
email.delivery_method method.to_sym, options
email.to = to
email.from = from
email.cc = cc
email.bcc = bcc
email.reply_to = reply_to
email
end
end
end
end