JavaScriptのGmail APIでメール送信する時のBase64エンコード

  • 13
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

@laco0416 です。前にDartでも同じような記事書いたけどJavaScriptでも同じことしようとしたら躓いた。

日本語メールをGmail APIで送るのに必要なステップ

日本語というかマルチバイトなUTF-8文字列をGmail APIで扱えるBase64文字列に変換する。

  1. 件名(Subject)をURL-UnsafeなBase64文字列にエンコードする
  2. メール全体をURL-SafeなBase64文字列にエンコードする

Subjectに個別のエンコードが必要な理由は最初に触れたDartの方の記事で書いてるので気になる方は参照してほしい。

URL-UnsafeなBase64文字列

普通にJavaScriptでBase64に変換するとこっちになる。

日本語を含まない場合は

window.btoa(str);

でいいが、日本語が入る場合は

window.btoa(unescape(encodeURIComponent(str)));

で、非ASCII文字をエンコードした後にBase64化する必要がある

URL-SafeなBase64文字列

通常のBase64には+/が使われているが、URL-SafeなBase64ではこれらを変換する必要がある。Dartでは関数のオプションで指定できたが、JavaScriptでは専用の関数が用意されていないので自力でやる必要がある。上記のURL-UnsafeなBase64を作った後に、次の置換を入れる

str.replace(/\+/g, '-').replace(/\//g, '_');

適当なサンプル

メールの組み立てはこんな感じになる

var mail = [
        "To: $to",
        "Subject: =?utf-8?B?$subject?=",
        "MIME-Version: 1.0",
        "Content-Type: text/plain; charset=UTF-8",
        "Content-Transfer-Encoding: 7bit",
        "",
        "$body"
      ].join("\n").trim();
mail = mail
  .replace("$to", this.to)
  .replace("$subject", window.btoa(unescape(encodeURIComponent(this.subject))))
  .replace("$body", this.body);
var encoded = window.btoa(unescape(encodeURIComponent(mail)))
  .replace(/\+/g, '-').replace(/\//g, '_');
sendMail(encoded); 

Gmail APIのドキュメントが間違ってる

ところで、Gmail APIのドキュメントではmessages.sendのサンプルコードは次のようになっている

ドキュメントのサンプルコード
function sendMessage(userId, email, callback) {
  var base64EncodedEmail = btoa(email);
  var request = gapi.client.gmail.users.messages.send({
    'userId': userId,
    'message': {
      'raw': base64EncodedEmail
    }
  });
  request.execute(callback);
}

が、これはバージョンが古く、現在はmessageではなくresourceプロパティにメールの文字列を渡すようになっている。

今動くやつ
function sendMessage(userId, email, callback) {
  var base64EncodedEmail = btoa(email);
  var request = gapi.client.gmail.users.messages.send({
    'userId': userId,
    'resource': {
      'raw': base64EncodedEmail
    }
  });
  request.execute(callback);
}

フィードバックは送ったが、ドキュメントにバージョンを書くか、更新するかどっちか(できればどっちも)やってほしい。