GASでGmailをSlackに通知する
動機
defaultの機能だとSlackbotにしか転送できない
channelごとの振り分けは有料のSlack appを導入しないといけない
目的
Slackのchannelを指定してGmailのメールを転送する
これやりたい
使い方
1. https://script.google.com にアクセスして適当にprojectを作る
2. main.gs, settings.gs, blockKit.gs, をコピペする
3. settings.gsに適当に設定を書く
4. 時間主導型タイマーを設定する
1分ごとでもいい気がするtakker.icon
そんなに周期速くて制限に引っかかったりしないのですか?
GASって制限ありましたっけ?
Google APIにAPI rateがあるんだから、GASにもあるか
まあ10分くらいでも十分そう
2021-03-27 05:19:48 できた
実装
GASでGmailをSlackに転送する |Logical Dice Techlogを一部改変している
もっともこの状態では使えないと思う
Slack APIが古い
Block kitを使ったコードに組み替える必要がある
詳しく調べないとtakker.icon
作り変えた
3つの段階に分ける
検索queryを元にメールを検索する
GmailApp.search()
Slackの各channelに投稿する
投稿したメールを全て既読にする
設定変数を用意する
以下をセットにした配列
検索query生成関数
実行時の日付を受け取れるようにする
投稿先channelのweb hook
実装すること
Threadのうち、最新のメールだけを取り出す
これすこし実装が難しいかも
検索クエリで、threadから特定日時のものだけを取り出せるような仕組みがあればいいんだけど
Threadから最新のメールだけ返せばいいか
大抵は、一連メールが自動で最新のメールの本文末尾に書き込まれている
それ見りゃだいたいわかるだろtakker.icon
リッチにする
以下を先頭にcontextで入れる
送信日時
形式:Date: {date}
送信元:From: {address}
宛先:To: {address}
件名
メッセージのタイトルに入れるからいらない
code:main.gs(js)
function main() {
const now = (new Date()).getTime();
const threads = settings.flatMap(({ channel, query }) => {
const threads = GmailApp
.search(query(now));
console.log(send ${threads.length} messages);
console.log(query: ${query(now)});
return threads.map(thread => {
// 最新のメールだけ取得する
const message = thread.getMessages().pop();
send(message, channel);
return thread;
});
});
// 最後にまとめて既読にする
threads.forEach(thread => thread.markRead());
}
function send(message, channel) {
const body = {
text: message.getSubject(),
...blocks(
header(message.getSubject()),
context(mrkdwn([
Date: ${message.getDate()},
From: ${message.getFrom()},
To: ${message.getTo()},
].join('\n'))),
section(message.getPlainBody()),
),
};
try {
UrlFetchApp.fetch(channel, {
method: 'POST',
contentType: 'application/json',
payload: JSON.stringify(body),
muteHttpExceptions: true,
});
} catch (e) {
console.error(e);
}
}
code:settings.gs(js)
const settings = [
{
query: (today) => in:inbox is:unread after:${parseInt((today - 10 * 60 * 1000) / 1000)},
channel:'webhook URL',
},
];
easyBlockKitGeneratorをコピーしたやつ
code:blockKit.gs(js)
const em = text => _${text}_;
const strong = text => *${text}*;
const strike = text => ~${text}~;
const br = '\n';
const p = text => \n${text}\n;
const blockquote = text => > ${text};
const code = text => \`${text}\`;
const pre = text => \`\`\`${text}\`\`\`;
const a = ({href}, text) => <${href}${text ? |${text} : ''}>;
const hr = {type: 'divider'};
const blocks = (...items) => {return {blocks: items};};
const header = (text) => {
return {
type: 'header',
text: plain_text(text),
};
}
const section = (text, {plain = false} = {}) => {
return {
type: 'section',
text: plain ? plain_text(text) : mrkdwn(text),
};
};
const context = (...elements) => {
return {
type: 'context',
elements,
};
};
const mrkdwn = (text, {verbatim = true} = {}) => {
return {
type: 'mrkdwn',
text,
verbatim,
};
};
const plain_text = (text, {emoji = true} = {}) => {
return {
type: 'plain_text',
text,
emoji,
};
};
const image = (url, alt_text) => {
return {
type: 'image',
url,
...(alt_text ? {alt_text} : {}),
};
};