1

我的应用程序使用 mailman gem(也使用邮件)从外部服务器读取电子邮件时遇到问题。

ruby 1.9.2p0
mail (2.3.0)
mailman (0.4.0) 
actionmailer (= 3.1.3)

数据库.yml

production:
  adapter: mysql2
  encoding: utf8

这是接收“邮件”的简单方法。我从多部分电子邮件的 text_part(例如,带有附件)或整个正文(已解码)构建 @message_body。

def self.receive_mail(message)
    # some code here 
    @message_body = message.multipart? ? message.text_part.body.to_s : message.body.decoded
    # some code here, to save message in database

我的问题是,如果消息没有附件但有变音符号,例如 ą ś ł ń ż ź ó ... 正文在第一个变音符号之前被拆分。因此,如果 body 是:“test żłóbek test”,我将在@message_body 中仅获得“test”。

我的问题是如何以一种优雅的方式保存这样的消息,以便文本部分与所有变音符号一起保存在数据库中。

编辑:为了让它更干净,我收到的电子邮件看起来像这样(它只是从 gmail 发送的电子邮件的一部分)

--20cf307ac4372d830104c11c8cc6 日期:2012 年 5 月 28 日星期一 20:06:16 +0200 Mime 版本:1.0 内容类型:文本/纯文本;charset=ISO-8859-2 内容传输编码:base64 内容 ID:<4fc3be989b76e_794650c25f6625e3@vk1057.some_domain>

dGVzdCC/s7zm8bbzsSB0ZXN0Cg==

所以我们有这个“身体”:dGVzdCC/s7zm8bbzsSB0ZXN0Cg==

解码后我们得到:'test \xbf\xb3\xbc\xe6\xf1\xb6\xf3\xb1 test\n'

问题是从 '\xbf' 开始的数据没有保存在数据库中。

更新

另一个例子,我认为这是这里的问题:

irb(main):008:0* require 'base64'
=> true
irb(main):009:0> a = "test źćłżąńś"
=> "test źćłżąńś"
irb(main):010:0> b = Base64.encode64(a)
=> "dGVzdCDFusSHxYLFvMSFxYTFmw==\n"
irb(main):011:0> Base64.decode64(b)
=> "test \xC5\xBA\xC4\x87\xC5\x82\xC5\xBC\xC4\x85\xC5\x84\xC5\x9B"

看,在 decode64 之后我的变音符号丢失了,该怎么做才能让它们回来?

4

2 回答 2

1
force_encoding('utf-8')

不起作用,因为数据不是 utf-8 - 您的邮件标题清楚地表明邮件正文是 ISO 8859-2。

Mysql2 假设一切都是 utf8 但不能将字节转换为 utf8 (因为 ruby​​ 不知道原始编码)所以你的非 ascii 字符被 mysql 丢弃

对于那一个字符串,您可以尝试

body.force_encoding('ISO-8859-2').encode('utf-8')

但你真的想从内容类型标头中找出要使用的编码。我很惊讶邮件宝石没有为你做那件事

于 2012-05-28T20:18:12.217 回答
0

我有解决办法。的串联

.force_encoding("ORIGINAL_CHARSET").encode("UTF-8")

电子邮件正文对象上的方法是解决方案。

我不得不将我的receive_mail()定义从以前的“一个班轮”更改为:

if message.multipart?
    charset = message.text_part.content_type_parameters[:charset]
    @message_body = message.text_part.body.to_s.force_encoding(charset).encode("UTF-8")
else
    charset = message.content_type_parameters[:charset]
    @message_body = message.body.decoded.force_encoding(charset).encode("UTF-8")
end

有了这个结构,我可以检测到原始电子邮件的字符集是什么,然后强制它并编码回 UTF-8。这确保了从原始到 utf-8 的 base64 正确解码。

如果有人有更优雅的解决方案,请分享。

于 2012-05-28T20:22:57.670 回答