はじめに

GoでGmail APIを触っていた際に、「本文」は正しく日本語が表示されるのに「件名(subject)」が文字化けする事象に遭遇しました。

Gmail APIには、base64urlにエンコードしたstringを渡します。
下記のようなコードだと、件名の部分で 文字化け が発生します。

package main

import (
    "encoding/base64"
    ...
    "google.golang.org/api/gmail/v1"
)

func main() {
    ...
    msgStr := "to: hoge@gmail.com\n" + "subject: 件名\n\n" + "message: 本文"
    msg := []byte(msgStr)
    message := gmail.Message{}
    message.Raw = base64.URLEncoding.EncodeToString(msg)
    ...
}

ハマりどころ

メールのヘッダー部分(subjectを含む)は、「7ビットアスキーコード」でなければなりません。
参考:http://hogem.hatenablog.com/entry/20100122/1264169093

Goの文字エンコーディングはUTF-8であり、1ビットが破棄され日本語文字化けを引き起こしていました。

対処法

下記の流れで変換してあげました。

UTF-8(Go文字列でのデフォ) -> ISO-2022-JP -> (byteスライス) -> base64urlString
package main

import (
    "encoding/base64"
    "io/ioutil"
    "strings"
    "golang.org/x/text/encoding/japanese"
    "golang.org/x/text/transform"
    ...
    "google.golang.org/api/gmail/v1"
)

// Convert UTF-8 to ISO2022JP
func toISO2022JP(str string) ([]byte, error) {
    reader := strings.NewReader(str)
    transformer := japanese.ISO2022JP.NewEncoder()

    return ioutil.ReadAll(transform.NewReader(reader, transformer))
}

func main() {
    ...
    msgStr := "to: hoge@gmail.com\n" + "subject: 件名\n\n" + "message: 本文"
    // ISO-2022-JP(JISコード) へ一度変換する
    msgISO2022JP, _ := toISO2022JP(msgStr)
    msg := []byte(msgISO2022JP)
    message := gmail.Message{}
    message.Raw = base64.URLEncoding.EncodeToString(msg)
    ...
}

参考:http://qiita.com/spiegel-im-spiegel/items/2e475b48226330aa5570

おまけ

下記のレポジトリで実際に使っています。
https://github.com/yyoshiki41/go-gmail-drafts

广告
将在 10 秒后关闭
bannerAds