Google Driveにバックアップしておいたeml形式のメールデータをApps Scriptで読み込んでみました。文字コードがISO-2022-JP(7bit JIS)だったのですが、Apps ScriptのUtilities
のおかげでいい感じに読めました。
ISO-2022-JPのeml形式データを読み込むには
生データにISO-2022-JP
と書いてあったので、文字コードをJIS
に指定して読み込みます。
const driveUrl = 'https://drive.google.com/drive/folders/...';
const folderId = driveUrl.split('/')[5];
const childFolderName = 'backups'; // driveUrlの下にあるフォルダー名
const fileName = 'a.eml'; // フォルダーの下にあるファイル名
const file = DriveApp.getFolderById(folderId).getFoldersByName(childFolderName).next().getFilesByName(fileName).next();
const eml = file.getBlob().getDataAsString('JIS');
これでメール本文は解読できたのですが、ヘッダーのSubject、From、Toなどにある日本語が読めません。
ISO-2022-JPのヘッダーを読み込むには
どれも=?ISO-2022-JP?B?
と書いてあります。B
はbase64によるエンコードなので、
function decodeJis(encoded) {
return encoded.replace(/=\?ISO-2022-JP\?B\?(.*?)\?=/ig, (a, b) => Utilities.newBlob(Utilities.base64Decode(b)).getDataAsString('JIS'));
}
という関数を作って解読しました。こんな風に使います。
function test() {
const encoded = '=?ISO-2022-JP?B?GyRCJDMkcyRLJEEkTxsoQg==?==?ISO-2022-JP?B?GyRCJDMkcyRLJEEkTxsoQg==?=';
const decoded = decodeJis(encoded);
console.log(decoded);
//こんにちはこんにちは
}
ヘッダーを解析するには
かなり力技ですが、ヘッダーを読み込んでオブジェクト形式に変換する関数も作ってみました。車輪の再発明は楽しいですね!
sepはセパレーターです。\n
の場合と、\r\n
の場合があります。
function parseHeaders(headers, sep='\n') {
const set = (obj, line) => {
const sep = ': ';
const [key, ...values] = line.split(sep);
const k = key.toLowerCase().replace(/-/g, '_');
const value = values.join(sep);
if (obj[k] && Array.isArray(obj[k])) {
obj[k].push(value);
} else if (obj[k]) {
obj[k] = [obj[k], value];
} else {
obj[k] = value;
}
};
let line = '';
const ojb = headers.split(sep).reduce(prev, curr) => {
if (curr.includes(': ')) {
if (line) set(prev, line);
line = decodeJis(curr);
return prev;
}
line += decodeJis(curr);
return prev;
}, {});
if (line) set(obj, line);
return obj;
}
先ほどDriveから取得したeml
からヘッダーを解析してみます。
const eml = ... // 上記
const sep = data.includes('\r\n') ? '\r\n' : '\n';
const [headersPart, ...body] = data.split(sep + sep); // 空行2つがヘッダーとボディーの切れ目
const headers = parseHeaders(headersPart, sep);
console.log(headers);
// { "subject": "...", "from": "...", "to": "...", ... }