Ruby on Rails

Quoted-printable – crossing the 1000 character SMTP barrier

While sending some lengthy text files as email attachments, I discovered that some of my sentences were broken mid-word into new lines. Turns out, SMTP protocol allows only 1000 characters per line. Each line is to be wrapped at 998 characters by a CRLF (\r\n). Now, most email platforms such as Mandrill and SendGrid follow this rule, but Gmail seems to bypass it somehow. This prompted me to further look into workarounds to keep the attachment formatting as is.

Action Mailer Rails Guides tell you that the Mail gem automatically guesses the attachment content type, encoding and creates the attachment. The default content-type is ‘plain/text’. So I tried playing around with different content-types/ mime-types, for example text/tab-separated-values (Since I had a tab separated format) hoping they would be treated differently from plain text. But that didn’t do the trick.

After reading up some more about the SMTP line limits, I realised the problem was with the limitations of 7-bit encoding that SMTP uses to encode ASCII characters in mail.

Though the guides say that Base64 encoding is used for attachments, it is not so for all types of content. The Mail gem by default uses the 7-bit encoding for text attachments like text/plain, text/html, text/tab-separated-values, etc.

Log of an Email with text attachment:
Date: Sat, 20 Jun 2015 22:00:21 +0530
From: no-reply@example.com
To: example@gmail.com
Message-ID: <5585951dc476c_426f79f338660c9@lazyfish.mail>
Subject: Sample Mail with text attachment
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="--==_mimepart_5585951dc038b_426f79f338659c8";
charset=UTF-8
Content-Transfer-Encoding: 7bit
----==_mimepart_5585951dc038b_426f79f338659c8

Content-Type: text/plain;
charset=UTF-8;
filename=test.txt
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename=test.txt
Content-ID: <5585951db84fe_426f79f338658bf@lazyfish.mail>
This is plain text attachment
----==_mimepart_5585951dc038b_426f79f338659c8

Content-Type: text/html;
charset=UTF-8
Content-Transfer-Encoding: 7bit

<body><p>Html Email Body</p></body> ----==_mimepart_5585951dc038b_426f79f338659c8--

The most obvious way to solve the problem would be to use base64 encoding explicitly. However, base64 encoding is designed to be efficient for non-text 8 bit and binary data. It may also increase the file size by up to 33%. Exploring other encoding options available, there is a better encoding format suited to human readable ASCII text files, namely ‘quoted-printable‘.

Quoted-printable encoding format states that encoded lines of data must not be longer than 76 characters. To satisfy this limit without altering the encoded text, soft line breaks are used. A soft line break consists of an “=” at the end of an encoded line, and does not appear as a line break in the decoded text. These soft line breaks allow encoding text without line breaks (or 1000 character plus long lines).

Your mailer will look like:
attachments['test.txt'] = {
mime_type: "text/plain",
content_transfer_encoding: "quoted-printable",
content: File.read('path/to/test.txt')
}

So, now you can send lengthy text attachments without worrying about the 1000 character limit breaking your content formatting.
Happy mailing!

2 thoughts on “Quoted-printable – crossing the 1000 character SMTP barrier

Leave a comment