Switching from Postmark to Postfix - ruby-on-rails

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.

Related

Rails 3.1 mail encoding issue

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?

How to add to options hash only if a condition is true?

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

How to use Rhodes without Rhosync or RhoConnect?

I know we can sync data using rhodes without Rhosync or Rhoconnect by using direct web service, but I'm here little bit confuse where to place that code for webservice call and how do we initialize it. Can anyone help me with small example?
Thanks in Advance.
I got it and it works for me.
class ProductController < Rho::RhoController
include BrowserHelper
# GET /product
def index
response = Rho::AsyncHttp.get(:url => "example.com/products.json",
:headers => {"Content-Type" => "application/json"})
#result = response["body"]
render :back => '/app'
end
# GET /product/{1}
def show
id =#params['id']
response = Rho::AsyncHttp.get(:url => "example.com/products/"+ id +".json",
:headers => {"Content-Type" => "application/json"})
#result = response["body"]
end
# GET /product/new
def new
#product = product.new
render :action => :new, :back => url_for(:action => :index)
end
# GET /product/{1}/edit
def edit
id =#params['product_id'].to_s
response = Rho::AsyncHttp.get(:url => "example.com/products/#{id}.json",
:headers => {"Content-Type" => "application/json"})
#result = response["body"]
end
# POST /product/create
def create
name = #params['product']['name']
price = #params['product']['price']
body = '{"product" : {"name" : "'+ name +'","price" :"'+ price +'" } }'
#result = Rho::AsyncHttp.post(:url => "example.com/products.json",
:body => body, :http_command => "POST", :headers => {"Content-Type" => "application/json"})
redirect :action => :index
end
# POST /product/{1}/update
def update
name=#params['product']['name']
price=#params['product']['price']
body = '{"product" : {"name" : "' + name + '","price" :"' + price + '" } }'
id = #params["product_id"].to_s
response = Rho::AsyncHttp.post(:url => "example.com/products/#{id}.json",
:body => body, :http_command => "PUT",:headers => {"Content-Type" => "application/json"})
redirect :action => :index
end
# POST /product/{1}/delete
def delete
id = #params["product_id"].to_s
response = Rho::AsyncHttp.post(:url => "example.com/products/#{id}.json",
:http_command => "DELETE",
:headers => {"Content-Type" => "application/json"})
redirect :action => :index
end
end
Most easy form of http server request is next:
Rho::AsyncHttp.get(
:url => "http://www.example.com",
:callback => (url_for :action => :httpget_callback)
)
where httpget_callback is name of the controller callback method.
See more details at official Rhodes docs.

generating email address images or something which can't be easily scraped

I'm looking for a better Text-to-image solution for my Rails project to replace my current method which is generating a png using ImageMagick every time a new record is created or updated.
I want to prevent a mass scraping of data and abuse of email addresses provided. I'm wondering if there is an API to generate the text or use of javascript, or SVG, etc. Anything short of Flash.
I'm looking for a better solution than my current method:
def create_new_email_image
if email_changed?
path_to_images = '/images/emails'
puts "Connecting to AWS..."
config = YAML.load(File.open("#{RAILS_ROOT}/config/s3_credentials.yml"))[RAILS_ENV]
AWS::S3::Base.establish_connection!(
:access_key_id => config['access_key_id'],
:secret_access_key => config['secret_access_key']
)
puts "Finding S3 bucket..."
begin
bucket = AWS::S3::Bucket.find config['bucket_name']
rescue AWS::S3::NoSuchBucket
AWS::S3::Bucket.create config['bucket_name']
bucket = AWS::S3::Bucket.find config['bucket_name']
end
images_path = "#{RAILS_ROOT}/tmp/"
file_name = "#{id}.png"
#file_name = "5056.png"
file_path = images_path + "/"+ file_name
File.delete file_path if File.exists? file_path
img = Magick::Image.new(400, 22) { self.background_color = 'transparent' }
img.format = 'PNG'
text = Magick::Draw.new
text.annotate(img, 0, 0, 1, 0, "#{email}") {
self.gravity = Magick::WestGravity
self.pointsize = 18
self.fill = '#000000'
self.kerning = -1
self.font_weight = Magick::BoldWeight
}
img.write file_path
if AWS::S3::S3Object.exists? file_name, bucket.name + path_to_images
puts "file exists (deleting)"
AWS::S3::S3Object.delete file_name, bucket.name + path_to_images, :force => true
end
AWS::S3::S3Object.store file_name,
File.open(file_path),
bucket.name + path_to_images,
:content_type => 'image/png',
:access => :public_read,
:reload => true
`rm #{file_path}`
end
end
Rails provides a mail_to helper.
mail_to "me#domain.com"
# => me#domain.com
mail_to "me#domain.com", "My email", :encode => "javascript"
# => <script type="text/javascript">eval(decodeURIComponent('%64%6f%63...%27%29%3b'))</script>
mail_to "me#domain.com", "My email", :encode => "hex"
# => My email
mail_to "me#domain.com", nil, :replace_at => "_at_", :replace_dot => "_dot_", :class => "email"
# => me_at_domain_dot_com
mail_to "me#domain.com", "My email", :cc => "ccaddress#domain.com",
:subject => "This is an example email"
# => My email
The :encode => "hex" or :encode => "javascript" options are what you are looking for.
I've had the same problem. Here is my solution:
def text_to_image(text,options={})
return if text.blank?
filename=get_text_file_path(text)
unless File.exists?(filename)
gc = Magick::Draw.new
gc.fill = options[:color] unless options[:color].blank?
gc.pointsize options[:size] unless options[:size].blank?
gc.font=options[:font] unless options[:font].blank?
gc.gravity = Magick::CenterGravity
gc.text(0,0, text)
metrics=gc.get_type_metrics(text)
image = Magick::Image.new(metrics.width, metrics.height){
self.background_color = 'transparent'
}
gc.draw(image)
image.write(filename)
end
end
I use after_save callback to update graphic cache of email attribute.

The email body is missing when I send mails with attachements using ActionMailer

The content in the view is not being displayed. Only the attachment is being sent. Help would be appreciated!
def send
#subject = "Status of PIS App"
#recipients = "ssg#gmail.com"
#from = APP_CONFIG[:email]
#sent_on = Time.now
##content_type = "text/html"
content_type = "multipart/alternative"
attachment :filename => "Report.html",:content_type => "text/html",
:body => File.read("/home/shreyas/repos/mysorepoc/app/models/new1.html")
end
When using attachments, you need to specify the text part separately:
def send
#subject = "Status of PIS App"
#recipients = "ssg#gmail.com"
#from = APP_CONFIG[:email]
#sent_on = Time.now
##content_type = "text/html"
content_type = "multipart/mixed"
part :content_type => "text/plain", :body => "contents of body"
attachment :filename => "Report.html",:content_type => "text/html", :body => File.read("/home/shreyas/repos/mysorepoc/app/models/new1.html")
end
And you probably want to send the mail as a multipart/mixed, not as multipart/alternative (unless the attachment really is an alternative representation of the text part).

Resources