In my Rails project I have this mailer class:
class ProjectMailer < ActionMailer::Base
def send_project_link(delivery)
#delivery = delivery
mail(:from => #delivery.sender_email,
:to => #delivery.recipient_email,
:bcc => [#delivery.sender_email],
:subject => #delivery.subject)
end
end
What is the cleanest way to either include or not include the key/value pair :bcc in the hash, depending on whether true or false is given?
Thanks for any help.
mail(
{
from: #delivery.sender_email,
to: #delivery.recipient_email,
subject: #delivery.subject,
}
.tap{|h| h[:bcc] = [#delivery.sender_email] if #delivery}
)
To not include the :bcc key in the options, you could do this:
class ProjectMailer < ActionMailer::Base
def send_project_link(delivery, send_with_bcc=false)
#delivery = delivery
mail_options = {
:from => #delivery.sender_email,
:to => #delivery.recipient_email,
:subject => #delivery.subject
}
mail_options[:bcc] = [#delivery.sender_email] if send_with_bcc
mail(mail_options)
end
end
I'd probably do this...
def send_project_link(delivery. bcc? = false)
#delivery = delivery
mail_options = {:from => #delivery.sender_email,
:to => #delivery.recipient_email,
:subject => #delivery.subject
}
mail_options[:bcc] = [#delivery.sender_email] if bcc?
mail mail_options
end
Related
We want to switch from Postmark to Postfix, but with Postfix the mail with the attachment(PDF file) is arriving as garbage:
Date: Sun, 10 Apr 2016 13:17:56 +0300
Mime-Version: 1.0
Content-Type: application/pdf; charset=UTF-8; filename=test_order1460278254278.pdf
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=test_order1460278254278.pdf
Content-ID: <570a2854317a9_1c6f12f77f841854#app1.mail>
JVBERi0xLjQKJeLjz9MKNSAwIG9iago8PC9CYXNlRm9udC9QV1dNR1QrQXJp
YWxNVC9EZXNjZW5kYW50Rm9udHNbNiAwIFJdL1R5cGUvRm9udC9TdWJ0eXBl
L1R5cGUwL0VuY29kaW5nL0lkZW50aXR5LUgvVG9Vbmljb2RlIDkgMCBSPj4K
ZW5kb2JqCjEwIDAgb2JqCjw8L0Jhc2VGb250L1dYSkRSSytMdWNpZGFTYW5z
LVR5cGV3cml0ZXJCb2xkL0Rlc2NlbmRhbnRGb250c1sxMSAwIFJdL1R5cGUv
Rm9udC9TdWJ0eXBlL1R5cGUwL0VuY29kaW5nL0lkZW50aXR5LUgvVG9Vbmlj
b2RlIDE0IDAgUj4+CmVuZG9iagoxNSAwIG9iago8PC9CYXNlRm9udC9UaW1l
This is my code:
class UserMailer < ActionMailer::Base
default :from => "mailer#xodapp1.com"
default :bcc => "do_not_reply#xodapp1.com"
default :reply_to => "do_not_reply#xodapp1.com"
def send_email(agent, customer, subject, body, mail_to = nil, mail_cc = nil, url_attachment = nil , name_attachment = nil)
#attachments[name_attachment] = {:content => open(url_attachment).read, :mime_type => MIME::Types.type_for(name_attachment).first} unless url_attachment.nil?
mail_to = !mail_to.nil? ? mail_to : "\"#{customer.name}\" <#{customer.email}>"
mailers_to = mail_to.split(',')
mail_cc = !mail_cc.nil? ? mail_cc.split(',') : agent.email
if [nil, []].include?(mail_cc)
mail_cc = UserMailer.default[:bcc]
end
body = "Copy attached" if body.nil? || body.empty?
mail_obj = mail(:to => mailers_to,
:from => "\"#{agent.name}\" <mailer#xodapp1.com>",
:bcc => mail_cc,
:subject => subject,
:content_type => "text/html",
:body => body.html_safe,
:reply_to => "#{!agent.email.nil? ? agent.email : UserMailer.default[:reply_to]}"
)
mail_obj.attachments[name_attachment] = open(url_attachment).read unless url_attachment.nil?
return mail_obj
end
end
I remove the content_type and change the order:
class UserMailer < ActionMailer::Base
default :from => "mailer#cavsystems.com"
default :bcc => "do_not_reply#cavsystems.com"
default :reply_to => "do_not_reply#cavsystems.com"
def send_email(agent, customer, subject, body, mail_to = nil, mail_cc = nil, url_attachment = nil , name_attachment = nil)
#attachments[name_attachment] = {:content => open(url_attachment).read, :mime_type => MIME::Types.type_for(name_attachment).first} unless url_attachment.nil?
mail_to = !mail_to.nil? ? mail_to : "\"#{customer.name}\" <#{customer.email}>"
mailers_to = mail_to.split(',')
mail_cc = !mail_cc.nil? ? mail_cc.split(',') : agent.email
if [nil, []].include?(mail_cc)
mail_cc = UserMailer.default[:bcc]
end
body = "Copy attached" if body.nil? || body.empty?
attachments[name_attachment] = open(url_attachment).read unless url_attachment.nil?
mail(:to => mailers_to,
:from => "\"#{agent.name}\" <mailer#cavsystems.com>",
:bcc => mail_cc,
:subject => subject,
#:content_type => "text/html",
:body => body.html_safe,
:reply_to => "#{!agent.email.nil? ? agent.email : UserMailer.default[:reply_to]}"
)
#mail_obj.attachments[name_attachment] = open(url_attachment).read unless url_attachment.nil?
#return mail_obj
end
end
Now the email is arriving with the pdf attachment but the HTML code is raw :-(
It's o.k. because we need the pdf not the html.
It will be great if the HTML will be visible.
I have a Payment mailer class that creates email:
class PaymentMailer < ActionMailer::Base
include LocaleWrapper
helper :application
def payment_notification(payment)
host = payment.try(:host)
#payment = payment
#user = payment.user
using_locale((#user && #user.locale) || I18n.locale) {
attachments["#{set_default_domain_name_from(host)}_receipt_#{Time.now.strftime("%Y_%m_%d")}.pdf"] = WickedPdf.new.pdf_from_string(
render_to_string(pdf: "#{set_default_domain_name_from(host)}_receipt_#{Time.now.strftime("%Y_%m_%d")}.pdf", template: filtre_mail_template_by_host(host), layout: "pdf.html"))
headers['Precedence'] = 'bulk'
mail(:to => #user.email, :subject => I18n.t("mailer_subjects.payment_completed"), :from => "no-reply##{set_default_domain_name_from(host)}") do |format|
format.text(:content_transfer_encoding => "base64")
format.html
end
}
end
I have observer method that saves email in the database:
def delivered_email(email)
Rails.logger.info email.inspect
html_body = (email.multipart? ? email.html_part : email).body.to_s
text_body = (email.multipart? ? email.text_part : email).body.to_s
outgoing_mail = OutgoingMail.new({
:to => email.to.join(', '),
:from => email.from.join(', '),
:subject => email.subject.to_s,
:sent_at => email.date,
:html_body => html_body,
:text_body => text_body,
:multipart => email.multipart?,
})
outgoing_mail.save
save_attachments(email, outgoing_mail)
end
Problem is with multipart email's plain text version, which returns ASCII 8bit string and mysql throws Mysql2::Error: Incorrect string value error.
(rdb:1) text_body
"N\x16\xA7\x93*.~\x8A\xF2\xA2\xEA\xDC\xA2{k\x89\xBB\xAD\x8A\x89\xD2y\xEA]}\xABmi\xC8fz{_\xA2\xBAZ\xCAg\xA7\xB5\xD7\xADj)l"
(rdb:1) text_body.encoding
#<Encoding:ASCII-8BIT>
I have tried using #force_encoding method, but there is no success:
(rdb:1) text_body.force_encoding("UTF-8")
"N\u0016\xA7\x93*.~\x8A\xF2\xA2\xEAܢ{k\x89\xBB\xAD\x8A\x89\xD2y\xEA]}\xABmi\xC8fz{_\xA2\xBAZ\xCAg\xA7\xB5\u05EDj)l"
Why am i getting ASCII 8bit string instead of UTF-8?
I'm trying to import 90k lines of xml into my ruby app. herokus timeout limit is 30s so i'm trying to use delayed job.
The import class works wonderfully in around 48-hippopotomuses locally. When i add the line
handle_asynchronously :save_races
I get the error "undefined method save_races' for classXmltube'"
What am i doing wrong with DJ and how can i get this to work?
Full class code below
require "rexml/document"
class Xmltube
def self.convert_save(xml_data)
doc = REXML::Document.new xml_data.read
doc.elements.each("Meeting") do |meeting_element|
meeting = save_meeting(meeting_element)
save_races(meeting_element, meeting)
Rails.logger.info "all done"
end
end
def self.save_races(meeting_element, meeting)
meeting_element.elements.each("Races/Race") do |race_element|
race = save_race(race_element, meeting)
save_race_entrants(race_element, race)
end
end
def self.save_race_entrants(race_element, race)
race_element.elements.each("RaceEntries/RaceEntry") do |entry_element|
horse = save_horse(entry_element)
jockey = save_jockey(entry_element)
start = save_start(entry_element, horse, jockey, race)
save_sumaries(entry_element, start)
end
end
def self.save_track(meeting_element)
# there is only one track, but still, each? wtf.
t = {}
meeting_element.elements.each("Track") do |track|
t = {
:name => track.attributes["VenueName"],
:track_code => track.attributes["VenueCode"],
:condition => track.elements['TrackRating'].text,
:club_id => save_club(meeting_element.elements["Club"]).id
}
end
track = Track.where(:track_code => t[:track_code] ).first
if track
Track.update(track.id, t)
else
Track.create(t)
end
end
def self.save_meeting meeting_element
t = {
:meet_code => meeting_element.attributes['MeetCode'],
:stage => meeting_element.elements["MeetingStage"].text,
:phase => meeting_element.elements["MeetingPhase"].text,
:nominations_close_at => meeting_element.elements["NominationsClose"].text,
:acceptance_close_at => meeting_element.elements["AcceptanceClose"].text,
:riders_close_at => meeting_element.elements["RidersClose"].text,
:weights_published_at => meeting_element.elements["WeightsPublishing"].text,
:club_id => save_club(meeting_element.elements["Club"]).id ,
:track_id => save_track(meeting_element).id,
:tab_status => meeting_element.elements["TabStatus"].text,
:state => meeting_element.elements["StateDesc"].text,
:day_night => meeting_element.elements["DayNight"].text,
:number_of_races => meeting_element.elements["NumOfRaces"].text,
:meet_date => meeting_element.elements["MeetDate"].text,
}
meeting = Meeting.where(:meet_code => t[:meet_code] ).first
if meeting
Meeting.update(meeting.id, t)
else
Meeting.create(t)
end
end
############################################################
def self.save_sumaries entry_element, start
entry_element.elements.each('Form/ResultsSummaries/ResultsSummary') do | element |
s = {
:name => element.attributes['Name'],
:start_id => start.id,
:starts => element.attributes['Starts'],
:wins => element.attributes['Wins'],
:seconds => element.attributes['Seconds'],
:thirds => element.attributes['Thirds'],
:prize_money => element.attributes['PrizeMoney'],
}
sum = Summary.where(:name => s[:name] ).where(:start_id => s[:start_id]).first
if sum
Summary.update(sum.id, s)
else
Summary.create(s)
end
end
end
def self.save_start entry_element, horse, jockey, race
s = {
:horse_id => horse.id,
:jockey_id => jockey.id,
:race_id => race.id,
:silk => entry_element.elements["JockeySilksImage"].attributes["FileName_NoExt"],
:start_code => entry_element.attributes['RaceEntryCode'],
:handicap_weight => entry_element.elements['HandicapWeight'].text,
}
# Rails.logger.info entry_element['HandicapWeight'].text
start = Start.where(:start_code => s[:start_code] ).first
if start
Start.update(start.id, s)
else
Start.create(s)
end
end
def self.save_jockey entry_element
j={
:name => entry_element.elements['JockeyRaceEntry/Name'].text,
:jockey_code => entry_element.elements['JockeyRaceEntry'].attributes["JockeyCode"],
}
jockey = Jockey.where(:jockey_code => j[:jockey_code] ).first
if jockey
Jockey.update(jockey.id, j)
else
Jockey.create(j)
end
end
def self.save_horse entry_element
trainer = save_trainer entry_element
h= {
:name => entry_element.elements['Horse'].attributes["HorseName"],
:color => entry_element.elements['Horse'].attributes["Colour"],
:dob => entry_element.elements['Horse'].attributes["FoalDate"],
:sex => entry_element.elements['Horse'].attributes["Sex"],
:trainer_id => trainer.id,
:horse_code => entry_element.elements['Horse'].attributes["HorseCode"],
}
horse = Horse.where(:horse_code => h[:horse_code] ).first
if horse
Horse.update(horse.id, h)
else
Horse.create(h)
end
end
def self.save_trainer entry_element
t= {
:name => entry_element.elements['Trainer/Name'].text,
:trainer_code => entry_element.elements['Trainer'].attributes["TrainerCode"]
}
trainer = Trainer.where(:trainer_code => t[:trainer_code] ).first
if trainer
Trainer.update(trainer.id, t)
else
Trainer.create(t)
end
end
def self.save_club element
t = {}
t = {
:club_code => element.attributes['ClubCode'],
:title => element.attributes["Title"],
}
club = Club.where(:club_code => t[:club_code] ).first
if club
Club.update(club.id, t)
else
Club.create(t)
end
end
def self.save_race element, meeting
r = {
:name => element.elements['NameRaceFull'].text,
:occur => element.elements['RaceStartTime'].attributes["TimeAtVenue"],
:distance => element.elements['RaceDistance'].text,
:race_type => element.elements['RaceType'].text,
:track_id => meeting.track_id,
:race_code => element.attributes["RaceCode"],
:meeting_id => meeting.id
}
race = Race.where(:race_code => r[:race_code] ).first
if race
Race.update(race.id, r)
else
Race.create(r)
end
end
handle_asynchronously :save_races
end
Since your save_races is a class method, you should call handle_asynchronously on Xmltube's singleton class:
class << self
handle_asynchronously :save_races
end
This just worked as I would expect
class Foo
def self.bar(s)
Rails.logger.info "From Foo.bar('#{s}')"
end
end
# then ...
Foo.delay.bar('hello')
I was running 4.0.4 of DJ with ruby 2.1
In my mailers/event_mailer class, I have a few methods. Each of these methods:
Receives a user hash an input
Turns the user hash into a global variable
calls a the corresponding .html.erb file from event_mailers to send email
Instead of repeating steps 1 & 2 for every method, is there a way to have that initialized once in a "constructor" for the event_mailer class?
Clarification Code:
Registrations Controller Code:
EventMailer.notify_admins(#user,subject,topic).deliver
event_mailer.rb code:
class EventMailer < ActionMailer::Base
##smtp_settings = {
..........
}
def notify_admins(user,subject,topic)
#user = user
#topic = topic
......
mail(:from => 'test#example.com', :to => 'someone#someone.com', :subject => subject)
end
def notify_accounts(user,subject,topic)
#user = user
#topic = topic
......
mail(:from => 'test#example.com', :to => 'someone#someone.com', :subject => subject)
end
active_scaffold :formats do |config|
format_order = Format.find(:all, :select => :format_order, :order => :format_order).collect(&:format_order)
format_order << format_order.size + 1 # I want only implement when new
config.columns = [:name, :format_order]
config.columns[:format_order].form_ui = :select
config.columns[:format_order].options = {
:options => format_order
}
config.list.columns = [:name, :format_order]
end
I want if I new format, format_order will add a number as code (format_order.size + 1) but I don't want implement it for edit. please help me. thanks
You will have to implement a callback:
class Format < ActiveRecord::Base
...
after_validation(:on => :create) do
self.code = whatever_code_you_want_to_assign #
end
...
end