2015-12-15 5 views
0

Я работаю с API-интерфейсом Inbound Email Mandrill, а когда электронное письмо имеет вложение с одним или несколькими пробелами в имени файла, то имя файла кодируется в формате, который я не использую знать, как декодировать.Как декодировать строку в Ruby

Вот пример строки я получаю для имени файла: =?UTF-8?B?TWlzc2lvbmFyecKgRmFpdGjCoFByb21pc2XCoGFuZMKgQ2FzaMKgUmVjZWlwdHPCoFlURMKgMjUzNQ==?= =?UTF-8?B?OTnCoEp1bHktMjAxNS5jc3Y=?=

Я попытался Base64.decode64(#{encoded_value}), но это не возвращает читаемый текст.

Как декодировать это значение в читаемую строку?

+0

Было бы полезно, если бы вы сказать нам, какой алгоритм вы говорите. –

+0

Используйте mime-декодер, просто подсказка для вас: 'puts Base64.decode64 («TWlzc2lvbmFyecKgRmFpdGjCoFByb21pc2XCoGFuZMKgQ2FzaMKgUmVjZWlwdHPCoFlURMKgMjUzNQ ==") 'производить' Миссионерская вера обещание и денежные поступления YTD 2535' –

ответ

1

Это MIME encoded-word syntax, как определено в RFC-2822. Материал из Википедии:

Форма является: "=?кодировок?кодирование?закодированный текст?=".

  • кодировок может быть любой набор символов зарегистрирован IANA. Обычно это будет тот же набор символов, что и тело сообщения.
  • кодирование может быть либо «Q», обозначающий Q-кодирования, который похож на quoted-printable кодирования, или «B», обозначающий base64 кодирование.
  • закодированный текст - это кодированный Q-кодированный или base64-текст.

К счастью, для этого вам не нужно писать декодер. Mail камня поставляется с методом Mail::Encodings.value_decode, который прекрасно работает и очень well-tested:

subject = "=?UTF-8?B?TWlzc2lvbmFyecKgRmFpdGjCoFByb21pc2XCoGFuZMKgQ2FzaMKgUmVjZWlwdHPCoFlURMKgMjUzNQ==?= =?UTF-8?B?OTnCoEp1bHktMjAxNS5jc3Y=?=" 
Mail::Encodings.value_decode(subject) 
# => "Missionary Faith Promise and Cash Receipts YTD 253599 July-2015.csv" 

Он изящно обрабатывает много краевых случаи вы, вероятно, не будете думать (пока приложение не пытается справиться с ними и падает):

subject = "Re:[=?iso-2022-jp?B?GyRCJTAlayE8JV0lcyEmJTglYyVRJXMzdDwwMnEbKEI=?=\n =?iso-2022-jp?B?GyRCPFIbKEI=?=] =?iso-2022-jp?B?GyRCSlY/LiEnGyhC?=\n =?iso-2022-jp?B?GyRCIVolMCVrITwlXSVzIVskKkxkJCQ5ZyRvJDsbKEI=?=\n =?iso-2022-jp?B?GyRCJE43byRLJEQkJCRGIUolaiUvJSglOSVIGyhC?=#1056273\n =?iso-2022-jp?B?GyRCIUsbKEI=?=" 
Mail::Encodings.value_decode(subject) 
# => "Re:[グルーポン・ジャパン株式会社] 返信:【グルーポン】お問い合わせの件について(リクエスト#1056273\n )" 

Если вы используете Rails, у вас уже есть почтовый камень. В противном случае просто добавьте gem "mail" в свой Gemfile, затем bundle install и, в вашем скрипте, require "mail".

1

Благодаря комментарию от @ Евгения-Анфилофеева, который указал мне в правильном направлении, я смог написать следующий метод, который правильно разобрал кодированное значение и вернул строку ASCII.

def self.decode(value) 
    # It turns out the value is made up of multiple encoded parts 
    # so we first need to split each part so we can decode them seperately 
    encoded_parts = name.split('=?UTF-8?B?'). 
         map{|x| x.sub(/\?.*$/, '') }. 
         delete_if{|x| x.blank? } 

    encoded_parts.map{|x| Base64.decode64(x)}. # decode each part 
       join(''). # join the parts together 
       force_encoding('utf-8'). # force UTF-8 encoding 
       gsub("\xC2\xA0", " ") # remove the UTF-8 encoded spaces with an ASCII space 
end 
+0

Не будет ли этот код сбой, если кодировка не UTF-8? –

-1

Я хотел бы только исправить информацию, которую я видел выше ... RFC 2822 действительно рассматривает протокол SMTP, в частности. Кодируются слово определяется в RFC 1342

https://tools.ietf.org/html/rfc1342

+1

Это должен быть комментарий к ответу, а не новый ответ. –

Смежные вопросы