Convert header of email to another encoding in ActionMailer in Ruby - ruby-on-rails

I have a website written on ruby 1.8.5 and rails 1.2.6.
There is a feedback page.
So.
i've got a model class:
class Feedback::Notify < ActionMailer::Base
def answer_for_managers(question)
recipients test#test.com
from "feedback#test.com"
subject "Обратная связь: ответ на вопрос"
body "question" => question
content_type "text/html"
end
end
Then i have a controller:
class Feedback::QuestionController < Office::BaseController
def update
Feedback::Notify.deliver_answer_for_managers(#question)
end
end
The problem is when a message is sent its subject looks like: =?utf-8?Q?=d0=9e=d0=b1=d1=80=d0=b0=d1=82=d0=bd=d0=b0=d1=8f_=d1=81=d0=b2=d1=8f=d0=b7=d1=8c=3a_=d0=a1=d0=be=d1=82=d1=80=d1=83=d0=b4=d0=bd=d0=b8=d0=ba_=d0=be=d1=82=d0=b2=d0=b5=d1=82=d0=b8=d0=bb_=d0=bd=d0=b0_=d0=b2=d0=be=d0=bf=d1=80=d0=be=d1=81_=d0=ba=d0=bb=d0=b8=d0=b5=d0=bd=d1=82=d0=b0_=23=35=36_=d0=be=d1=82_=32=36=2e=30=38=2e=32=30=31=31_=31=31=3a=33=33?=
so it's url-encoded.
Is there any way to prevent converting subject text to url-encoding?
All files are in UTF8 encoding

If you would put unescaped UTF-8 characters into header fields, you would be violating the respective standards RFC 822 and RFC 5322 which state that header fields can only be composed of (7-bit) ASCII characters.
Thus, ActionMailer does the right thing here and escapes the UTF-8 characters. As nothing in the headers states that another encoding is to be used, the recipient (and all intermediate servers) have no other chance than to follow that standard as they have no other clue which encoding might have been used.
As RFC 822 is rather old (but still authoritative for email), UTF-8 just didn't exist as it was specified. The escaping is a workaround specified by RFC 2047 which exactly specifies what you see in the header. MUAs are expected to unescape the text and display the proper glyphs on rendering.
Note that it is entirely possible to send unicode text inside the message body (most of the time inside a MIME container). There it is possible to specify the actual data encoding and the transport encoding using additional headers. See RFC 2045 ff. for more details.
Please read either the RFCs or have a look at the Wikipedia entry on Unicode and e-mail.

i solve my problem by adding default 'Content-Transfer-Encoding' => '7bit' in my ActionMailer
have a look in the API docs

Related

Encoding for special characters not working in email subject for sendgrid templates

I have been using the sendgrid-ruby gem for sending emails. The subject of the email doesn't decode special characters properly.
Eg. Sending this subject for the email How's it going translates to this in the actual email How&apos;s it going
I have tried encoding the string for subject to different formats such as ASCII, ISO_8859_1 but none of this works.
#body_json['personalizations'][0]['dynamic_template_data'] = {
'email_title': #email_title,
'content': #description,
'subject': "How's it going"
}
SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY']).client.mail._('send').post(request_body: #body_json)
The subject for email should show special characters correctly such as ' & :
You should be using triple brackets in your subject section i.e. {{{subject}}} for subjects with special characters.
If you use the double brackets approach your string is going to be HTML encoded.
Check this link from SendGrid repository https://github.com/sendgrid/sendgrid-nodejs/issues/741#issuecomment-422026634
Okay so after chatting with sendgrid support I was able to figure this out. The issue is not with the sendgrid request from my side. Whenever making a template always be sure that subject title in header is inside double brackets i.e. {{subject}}. This will ensure that all special characters work inside this block.

UTF-8 Chars in FTP Greeting

I tried to use Unicode characters in my FTP server's greeting, but the client seems to read them as two different characters each. Because of this, I need a way to encode them into UTF-8. For now, I have the greeting HTML encoded because I am displaying it on a webpage, but on any other client it will display the encoding. How can I set the greeting to be parsed as UTF-8? And if I can't, then is there a way I can parse the greeting correctly?
EDIT: Answered my own question, see below.
I found the answer to the question. It was actually UTF-8 encoded already, and I had to decode it from UTF-8. Here is what I did:
decodeURIComponent(escape(greeting))
Don't forget to replace the line breaks with <br> if you are displaying it on a webpage like I am!
decodeURIComponent(escape(greeting)).replace(/\n/g,'<br>')

Ignore � (non-UTF-8 characters) in email attachment or strip them from the attachment?

Users of our application are able to upload plain text files. These files might then be added as attachments to outgoing ActionMailer emails. Recently an attempt to send said email resulted in an invalid byte sequence in UTF-8 error. The email was not sent. This symbol, �, appears throughout the offending attachment.
We're using ActionMailer so although it ought to go without saying, here's representative code for the attachment action within the mailer class's method:
attachments['file-name.jpg'] = File.read('file-name.jpg')
From a business standpoint we don't care about the content of these text files. Ideally I'd like for our application to ignore the content and simply attach them to emails.
Is it possible to somehow tell Rails / ActionMailer to ignore the formatting? Or should I parse the incoming text file, stripping out non-UTF-8 characters?
I did search through like questions here on Stack Overflow but nothing addressed the problem I'm currently facing.
Edit: I did call #readlines on the file in a Rails console and found that the black diamond is a representation of \xA0. This is likely a non-breaking space in Latin1 (ISO 8859-1).
If Ruby is having problems reading the file and corrupting the characters during the read then try using File.binread. File.binread is inherited from IO
...
attachments['attachment.txt'] = File.binread('/path/to/file')
...
If your file already has corrupted characters then you can either find some process to 'uncorrupt' them, which is not fun, or strip them using by re-encoding from ASCII-8bit to UTF-8 stripping out the invalid characters.
...
attachments['attachment.txt'] = File.binread('/path/to/file')
.encode('utf-8', 'binary', invalid: :replace, undef: :replace)
...
(String#scrub does this but since you can't read it in as UTF-8 then you cant use it.)
With your edit, this seems pretty clear to me:
The file on your filesystem is encoded in latin1.
File.read uses the standard ruby encoding by default. If LANG contains something like "en_GB.utf8", File.read will associate the string with utf-8 encoding. You can verify this by logging the value of str.encoding (where str is the value of File.read).
File.read does not actually verify the encoding, it only slurps in the bytes and slaps on the encoding (like force_encoding).
Later, in ActionMailer, something wants to transcode the string, for whatever reason, and that fails as expected (and with the result you are noticing).
If your text files are encoded in latin1, then use File.read(path, encoding: Encoding::ISO_8859_1). This way, it may work. Let us know if it doesn't...
When reading the file at time of attachment, I can use the following syntax.
mail.attachments[file.file_name.to_s] = File.read(path_to_file).force_encoding("BINARY").gsub(0xA0.chr,"")
The important addition is the following, which goes after the call to File.read(...):
.force_encoding("BINARY").gsub(0xA0.chr,"")
The stripping and encoding ought to be done at time of file upload to our system, so this answer isn't the resolution. It's a short-term band-aid.

Isn't user data that comes in from a form in Rails going to be UTF-8 encoded?

A Rails 3.2 app I'm contributing to has a method that coerces user input to UTF-8.
require "iconv"
def normalize(user_input_text)
Iconv.new('UTF-8//IGNORE', 'UTF-8').iconv(user_input_text.dup)
end
It basically encodes the string in UTF-8 and ignores characters that can't be transcoded.
But isn't all user data that's entering Rails through a form going to be UTF-8 encoded?
In other words, isn't this code specious and unnecessary?
These resources suggest that indeed you are right.
Now that the vast majority of web input is UTF-8, we set
the inbound parameters to UTF-8. This will eliminate many
cases of incompatible encodings between ASCII-8BIT and
UTF-8.
https://github.com/rails/rails/commit/25215d7285db10e2c04d903f251b791342e4dd6a
Rails 3 solves this very nicely by doing a number of things including interpreting params as UTF-8 and adding workarounds for Internet Explorer
http://jasoncodes.com/posts/ruby19-rails2-encodings

How to use send an email with accents using actionmailer

My environment.rb is like this:
ActionMailer::Base.default_charset = "iso-8859-1"
which should be enough for accents, but here is how the message's subject is being sent:
Convite para participação de projeto
Does anyone know what I have to do to fix it?
Is your data in iso-8859-1? From the look of the error example, it seems to be two bytes per character (note the repetition of Ã). Since 8859-1 uses 1 byte per character, my guess is that your data is in utf-8 format.
Also check that your db is not doing any conversions on data going in or out.
I urge you to use unicode / utf-8 everywhere--database, html, emails, etc. It's what all of the kool-kids are using these days. 8859-1 is so last century!
Regarding emails
config.action_mailer.default_charset = "utf-8"
is what I use.
Just remove your setting and let Rails do the work using the default charset, UTF-8.
I work with emails and special characters all the time, there's no need to perform any kind of conversion or setting, at least not on Rails 3. As long as your strings contains the right characters, you'll be fine.
Just make sure the encoding error is not ocurring when reading the data from your database.

Resources