Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

@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);
}

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

lacolaco
I play Angular and pray for Angular. No Breaking Changes No Life.
https://lacolaco.net
classi
学校の先生・生徒・保護者向けのB2B2Cの学習支援Webサービス「Classi(クラッシー)」 を開発・運営している会社です。
https://classi.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away