Class: EmailNotification

Inherits:
Notification show all
Defined in:
lib/app/models/email_notification.rb

Overview

EmailNotification is a concrete class of Notification, sending emails to both members and users, or in the case of eCommerce, customers.

This object allows you to create an EmailNotification object, set it’s property and tell it send_notification. It’ll handle everything from there including

  1. Running in the background thread

  2. Error recovery

  3. Retry on failure

The Email object also uses the templating engine to allow the specification of a template and a set of local variables for dynamic content.

Usage:

email = EmailNotification.new email.to = ‘[email protected]’ email.recipient_name = ‘users name’ email.sender = ‘[email protected]’ email.subject = ‘Today is the day!’ email.message = ‘Day is today!’ email.send_notification

You are done! Go about your business of creating awesome software!

Constant Summary

Constants inherited from Notification

Notification::ALL_STATES, Notification::DELIVERY_EMAIL, Notification::DELIVERY_SLACK, Notification::DELIVERY_SMS, Notification::STATE_INVALID, Notification::STATE_NEW, Notification::STATE_PROCESSED, Notification::STATE_PROCESSING, Notification::STATE_RESUBMITTED, Notification::STATE_RETRYING, Notification::STATE_SUBMITTED, Notification::STATE_VIEWED

Instance Method Summary collapse

Methods inherited from Notification

#account_message_template, #default_message_template, #deletable?, #deliver_message, #delivery_channel, #finish_processing, #message_from_haml_file, #message_from_haml_text, #message_from_liquid_text, #message_from_template, #name, #render_liquid_text, #retry_delivery, #search_fields, #send_notification, #sendable?, #start_processing, #stringify_all, #successful?, #viewed

Methods included from SearchAble

#after_search_text, #before_search_text, included, #method_missing, #respond_to?, #respond_to_missing?, #search_fields, #sort_fields, #update_search_and_sort_text, #update_text

Methods included from StandardModel

#audit_action, #auto_strip_attributes, #capture_user_info, #clear_cache, #created_by_display_name, #delete_and_log, #destroy_and_log, included, #last_modified_by_display_name, #log_change, #log_deletion, #remove_blank_secure_fields, #save_and_log, #save_and_log!, #secure_fields, #update, #update!, #update_and_log, #update_and_log!

Methods included from App47Logger

clean_params, #clean_params, delete_parameter_keys, #log_controller_error, log_debug, #log_debug, log_error, #log_error, log_exception, #log_message, log_message, #log_warn, log_warn, mask_parameter_keys, #update_flash_messages

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class SearchAble

Instance Method Details

#account_smtp_configurationObject



188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/app/models/email_notification.rb', line 188

def 
  smtp = .fetch_smtp_configuration

  config = {
    address: smtp.server_name,
    port: smtp.port,
    authentication: smtp.authentication_method.to_sym,
    enable_starttls_auto: smtp.ssl.eql?(true)
  }
  config[:domain] = smtp.domain if smtp.domain.present?
  config[:user_name] = smtp.username if smtp.username.present?
  config[:password] = smtp.password if smtp.password.present?
  config
end

#account_subject_template(template_name) ⇒ Object



244
245
246
247
248
# File 'lib/app/models/email_notification.rb', line 244

def (template_name)
  .email_templates.find_by(name: template_name.to_s).subject
rescue StandardError
  nil
end

#add_attachments(attachments = nil) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/app/models/email_notification.rb', line 124

def add_attachments(attachments = nil)
  tmp_dir = Dir.mktmpdir
  attachments.each do |attachment|
    # Create a temp directory, it'll get cleaned up in the rescue.
    tmp_file_path = "#{tmp_dir}/#{attachment.file_file_name}"
    File.open(tmp_file_path, 'w') do |f|
      f.write(URI.parse(attachment.file_url).open.read.force_encoding('utf-16').encode)
    end
    mail.attachments[attachment.file_file_name] = {
      mime_type: attachment.file_content_type,
      content: File.open(tmp_file_path).read.force_encoding('utf-16').encode
    }
  end
end

#add_notification_tracker(html_message) ⇒ Object



216
217
218
219
220
221
222
# File 'lib/app/models/email_notification.rb', line 216

def add_notification_tracker(html_message)
  tracker_url = "#{SystemConfiguration.base_url}/notifications/#{id}/img"
  return html_message if html_message.include?(tracker_url)

  image_tag = "<img style='height:0;width:0;border:none;display:none;' src='#{tracker_url}' alt=''/></body>"
  html_message.sub(%r{</body>}, image_tag)
end

#build_messageObject

HTMLize messages



210
211
212
213
214
# File 'lib/app/models/email_notification.rb', line 210

def build_message
  clean_message = message.strip
  clean_message = "<html><body><pre>#{clean_message}</pre></body></html>" unless clean_message.start_with?('<')
  add_notification_tracker(clean_message)
end

#default_smtp_configurationObject



203
204
205
# File 'lib/app/models/email_notification.rb', line 203

def default_smtp_configuration
  SystemConfiguration.smtp_configuration
end

#deliver_message!Object

Add a file as an attachment to this email notification.

Expecting a path to the file, not the file or data itself. TODO consider how to handle a file object or data object.

Once you have called this method, the file is stored via PaperClip and does not need to stay persistant through email delivery. You can delete it after telling the EmailNotification to send the notification.

def add_file(file)

# Make sure we are saved
save! unless persisted?
attachment = EmailNotificationAttachment.new email_notification: self
attachment.file = open(file)
attachment.save!

end



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/app/models/email_notification.rb', line 70

def deliver_message!
  mail = Mail.new
  # Set the from line
  address = from_address
  mail.from = address
  self.from = address
  # Set the sender line
  address = sender_address
  mail.sender = address
  self.sender = address
  # Set the reply to
  address = reply_to_address
  if address.present?
    self.reply_to = address
    mail.reply_to = address
    mail.sender = address
  end

  # Set the to address
  mail.to = to

  # Set the cc line
  mail.cc = cc unless cc.nil?

  # Set the subject line
  mail.subject = subject

  # set the message body and send
  html_message = build_message
  mail.html_part do
    content_type 'text/html; charset=UTF-8'
    body html_message
  end

  # Add the attachments, if there are any. If not, none are added.
  add_attachments(attachments) if defined?(attachments)

  # Setup the delivery method for this message only.
  if 'test'.eql?(ENV['RAILS_ENV'])
    mail.delivery_method :test
  else
    mail.delivery_method :smtp, smtp_configuration
  end

  mail.header['X-Mailgun-Native-Send'] = 'yes' if SystemConfiguration.mail_gun_configured?
  # Deliver it
  mail.deliver
rescue StandardError => error
  # We are catching and rethrowing this only to allow the temp directory to be cleaned up in the ensure block
  raise error
ensure
  FileUtils.remove_entry_secure(tmp_dir) if defined?(tmp_dir) && tmp_dir.present?
end

#from_addressObject

From address



154
155
156
157
158
159
160
161
162
163
# File 'lib/app/models/email_notification.rb', line 154

def from_address
  return from if from.present?

  address = SystemConfiguration.default_email
  if .present?
     = .fetch_smtp_configuration
    address = .email_address if .use?
  end
  address
end

#from_template(template_name, locals = {}) ⇒ Object

has_many :attachments, class_name: ‘EmailNotificationAttachment’, dependent: :destroy



47
48
49
50
# File 'lib/app/models/email_notification.rb', line 47

def from_template(template_name, locals = {})
  super
  self.subject = subject_from_template(template_name, locals)
end

#reply_to_addressObject

Reply to address



168
169
170
171
172
173
174
175
176
177
# File 'lib/app/models/email_notification.rb', line 168

def reply_to_address
  return reply_to if reply_to.present?

  address = nil
  unless .nil?
    smtp = .fetch_smtp_configuration
    address = smtp.reply_to_address if smtp.use? && !smtp.reply_to_address.nil? && !smtp.reply_to_address.empty?
  end
  address
end

#sender_addressObject

sender address



142
143
144
145
146
147
148
149
# File 'lib/app/models/email_notification.rb', line 142

def sender_address
  address = SystemConfiguration.support_email
  if .present?
     = .fetch_smtp_configuration
    address = .username if .use?
  end
  address
end

#smtp_configurationObject

SMTP Configuration



182
183
184
185
186
# File 'lib/app/models/email_notification.rb', line 182

def smtp_configuration
  .get_smtp_configuration.use? ?  : default_smtp_configuration
rescue StandardError
  default_smtp_configuration
end

#subject_from_haml_text(haml_text, locals) ⇒ Object



224
225
226
227
228
# File 'lib/app/models/email_notification.rb', line 224

def subject_from_haml_text(haml_text, locals)
  locals[:base_url] = SystemConfiguration.base_url
  haml_engine = Haml::Engine.new(haml_text)
  self.subject = haml_engine.render(Object.new, stringify_all(locals))
end

#subject_from_liquid_text(liquid_text, locals) ⇒ Object



230
231
232
# File 'lib/app/models/email_notification.rb', line 230

def subject_from_liquid_text(liquid_text, locals)
  self.subject = render_liquid_text(liquid_text, locals)
end

#subject_from_template(template_name, locals) ⇒ Object



234
235
236
237
238
239
240
241
242
# File 'lib/app/models/email_notification.rb', line 234

def subject_from_template(template_name, locals)
  subject = (template_name) || Template.from_file(template_name, prefix: 'subject')
  if subject.present?
    subject_from_liquid_text(subject, locals)
  else
    subject = Template.from_file(template_name, format: 'haml', prefix: 'subject')
    subject.present? ? subject_from_haml_text(subject, locals) : nil
  end
end