GAS::メール類似度チェック
#2024/11/14
chatGPS君に手伝ってもらって,たどり着いた.
◆前提
学生のレポートをメールで受けている
中にはそっくりのレポートがあるので,それを見つけたい
精度はさほど必要ない
この作業を,gmailの中でやりたい
→ GASを使えば可能
◆メール受信の設定
1. 自分のgmailに242kj2というラベルを作成
2. その下にrep01~rep13のサブラベルを作成
3. gmailの振り分け機能で,To:レポート提出アドレスはすべて242kj2にラベル付けする
※だされたレポートはすべてここに集まるので,チェックの後は毎回のサブラベルに移動
4. 今回のレポートのみが242kj2にあるという状態になる
◆スクリプトの仕様
この242kj2にあるレポートをチェックするが,これに対して類似度をチェックしたい.
類似度でグループ分けするが,1通のグループは生成せず,2通以上のグループのみ生成.
ラベル付けの際には Mailchek という親ラベルを作成し,その下にグループラベルを再生する.
◆スクリプト生成手順
1. GoogleAppScriptの自分のページをオープン
https://script.google.com/u/1/home
2. プロジェクト新規作成し「メール類似度チェック」などと命名
3. Code.gsの欄に以下のコードを貼りつける
最初のrunGroupSimilarEmails()関数が実行用
groupSimilarEmails(readLabelName, parentLabelName)が分類用
引数は 1. 読み出すメールのラベル,2. チェック作業用ラベル
今回は "242kj2"と"Mailcheck"
4. スクリプトを保存する
5. 実行する関数を選択する:runGroupSimilarEmails
6. 実行ボタン
https://gyazo.com/00eb21384a0b32d8e8b869fd529b56e4
これで,Mailcheckラベルの下に,2通以上のグループができる
◆スクリプトコード
code:similarcheck.gs
function runGroupSimilarEmails() {
groupSimilarEmails("242kj2", "Mailcheck"); // 引数を指定
}
function getEmailsWithLabel(labelName, limit = 100) {
// 指定したラベルのメールを取得
const label = GmailApp.getUserLabelByName(labelName);
if (!label) {
Logger.log(ラベル "${labelName}" が見つかりません。);
return [];
}
const threads = label.getThreads(0, limit);
let emails = [];
threads.forEach(thread => {
const messages = thread.getMessages();
messages.forEach(msg => {
emails.push({
id: msg.getId(),
body: msg.getPlainBody(),
thread: thread // スレッドを保存
});
});
});
return emails;
}
function groupSimilarEmails(readLabelName, parentLabelName) {
// 指定されたラベルからメールを取得
const emails = getEmailsWithLabel(readLabelName);
if (emails.length === 0) {
Logger.log(ラベル "${readLabelName}" に該当するメールがありません。);
return;
}
let groups = [];
emails.forEach(email => {
let foundGroup = false;
for (let group of groups) {
const similarity = calculateJaccardSimilarity(email.body, group0.body);
if (similarity > 0.8) { // 80%以上の類似性で同じグループ
group.push(email);
foundGroup = true;
break;
}
}
if (!foundGroup) {
groups.push(email);
}
});
labelEmailsByGroups(groups, parentLabelName); // 指定された親ラベルの下に分類
}
function calculateJaccardSimilarity(text1, text2) {
const set1 = new Set(text1.split(/\s+/));
const set2 = new Set(text2.split(/\s+/));
const intersection = new Set(...set1.filter(x => set2.has(x)));
const union = new Set(...set1, ...set2);
return intersection.size / union.size;
}
function labelEmailsByGroups(groups, parentLabelName) {
// 親ラベルを確認、存在しない場合は作成
let parentLabel = GmailApp.getUserLabelByName(parentLabelName);
if (!parentLabel) {
parentLabel = GmailApp.createLabel(parentLabelName);
}
groups.forEach((group, index) => {
// 2通以上のメールがある場合のみサブラベルを作成
if (group.length > 1) {
const subLabelName = Similar Group ${index + 1};
const fullLabelName = ${parentLabelName}/${subLabelName};
const label = GmailApp.getUserLabelByName(fullLabelName) || GmailApp.createLabel(fullLabelName);
group.forEach(email => {
email.thread.addLabel(label);
});
}
});
}
#GAS