Edited at

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

More than 3 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);
}

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