电子邮件主题,标题解码在不同的字符集如ISO-2022-JP,GB-2312等

时间:2016-01-30 02:30:24

标签: go character-encoding decode non-ascii-characters

我正在开发一个需要处理不同字符集中的电子邮件编码/解码的项目。这个的python代码可以在下面显示:

from email.header import Header, decode_header, make_header
from charset import text_to_utf8    

class ....
def decode_header(self, header):
    decoded_header = decode_header(header)

    if decoded_header[0][1] is None:
        return text_to_utf8(decoded_header[0][0]).decode("utf-8", "replace")
    else:
        return decoded_header[0][0].decode(decoded_header[0][1].replace("windows-", "cp"), "replace")

基本上,对于像“=?iso-2022-jp?b?GyRCRW1CQE86GyhCIDxtb21vQHRhcm8ubmUuanA =?=”这样的文本; “decode_header”函数只是试图找到编码:'iso-2022-jp';然后它将使用“解码”功能将字符集解码为unicode。

现在,在go中,我可以做类似的事情:

import "mime"

dec := new(mime.WordDecoder)
text := "=?utf-8?q?=C3=89ric?= <eric@example.org>, =?utf-8?q?Ana=C3=AFs?= <anais@example.org>"
header, err := dec.DecodeHeader(text)

Seems that there mime.WordDecoder allow to put a charset decoder "hook": 
type WordDecoder struct {
   // CharsetReader, if non-nil, defines a function to generate
   // charset-conversion readers, converting from the provided
   // charset into UTF-8.
   // Charsets are always lower-case. utf-8, iso-8859-1 and us-ascii charsets
   // are handled by default.
   // One of the the CharsetReader's result values must be non-nil.
   CharsetReader func(charset string, input io.Reader) (io.Reader, error)
}           

我想知道是否有任何库可以允许我像python中的“decode”函数一样转换任意字符集,如上例所示。我不想写一个像mime / encodedword.go中使用的大的“switch-case”:

func (d *WordDecoder) convert(buf *bytes.Buffer, charset string, content []byte) error {
   switch {
   case strings.EqualFold("utf-8", charset):
      buf.Write(content)
   case strings.EqualFold("iso-8859-1", charset):
      for _, c := range content {
         buf.WriteRune(rune(c))
      }
....

非常感谢任何帮助。

感谢。

2 个答案:

答案 0 :(得分:1)

感谢。似乎golang.org/x/net/html/charset包已经提供了一个可用编码的地图。以下代码适用于我:

import "golang.org/x/net/html/charset"

CharsetReader := func (label string, input io.Reader) (io.Reader, error) {
    label = strings.Replace(label, "windows-", "cp", -1)
    encoding, _ := charset.Lookup(label)
    return encoding.NewDecoder().Reader(input), nil
}
dec := mime.WordDecoder{CharsetReader: CharsetReader}
text := "=?iso-2022-jp?b?GyRCRW1CQE86GyhCIDxtb21vQHRhcm8ubmUuanA=?="
header, err := dec.DecodeHeader(text)

感谢您的帮助!

答案 1 :(得分:0)

我不确定这是你在找什么,但有golang.org/x/text包用于将Windows-1251转换为UTF-8。代码看起来像

import (
    "golang.org/x/text/encoding/charmap"
    "golang.org/x/text/transform"
    "io/ioutil"
    "strings"
)

func convert(s string) string {
    sr := strings.NewReader(s)
    tr := transform.NewReader(sr, charmap.Windows1251.NewDecoder())
    buf, err := ioutil.ReadAll(tr)
    if err != nil {
        return ""
    }
    return string(buf)
}

我认为在你的情况下,如果你想避免“一个大的'切换案例'”,你可以用完整的可用编码列表创建一种地图,然后做出类似的事情:

var encodings = map[string]transform.Transformer{
    "win-1251": charmap.Windows1251.NewDecoder(),
}

func convert(s, charset string) string {
    buf, err := ioutil.ReadAll(transform.NewReader(strings.NewReader(s), encodings[charset]))
    if err != nil {
        return ""
    }
    return string(buf)
}