2024年12月10日に投稿された記事です。
目次
- 1. GASプロジェクトを作成する
- 2. 読みたい記事のフィードを登録する
- 3. 登録した記事をGmailに送信する
- 4. 毎日指定の時間に記事が送信されるようにする
- さいごに
こんにちは。dotDのエンジニアの前田です。
dotD Advent Calendar 2024の10日目になります。
この記事に書いてある手順を実施してくれたあなたは、「毎日決まった時間に興味のあるサイトの最新記事をGmailで受信」が叶います。
※フィードを提供しているサイトの記事であることを前提としています
スクリプトを作りますが、コピペして少し修正するだけなので、非エンジニアの方でも実現できます!
早速以下の手順をやっていきましょう!
1. GASプロジェクトを作成する
Googleドライブを開き、以下のように、「+新規」ボタンから「その他」→「Google Apps Script」を押下します。
以下が表示されたら、注意書きを読んで問題なかったら、「スクリプトを作成」を押下します。
以下の画面が表示されたらプロジェクト作成に成功です。
画面左上の「無題のプロジェクト」を押下すると、プロジェクト名が変更できるので、「記事をGmailに送信するスクリプト」など、わかりやすくしておきましょう。
2. 読みたい記事のフィードを登録する
画面左のファイルの横にある「+」ボタンを押下して、「スクリプト」を押下します。
ファイル名の入力が求められるので、「feedList」と入力すると、以下のように新規ファイルが作成されます。
次に、読みたい記事の登録方法について説明します。
まず、読みたい記事を公開しているサイトのフィードURLを取得します。
フィードを提供しているサイトなら、一般的にサイト内に「フィード」ボタンや「RSS」テキストリンクがあるので、そちらを押下してURLを取得します。
※公開されているフィードを利用する際は、必ず提供元のサイトの利用規約やポリシーを確認してください。一部のサイトでは、特定の用途においてフィード利用が制限されている場合があります。
以下の形式で、サイト名(名称は任意でok)とフィード名(名称は任意でok)とフィードURLを入力します。
const feedList = {
サイト名: [
{name: "フィード名", url: "フィードURL"},
],
};const feedList = {
サイト名: [
{name: "フィード名", url: "フィードURL"},
],
};
copy
あるサイトの最新記事を受け取りたい場合の例です。
const feedList = {
exampleSite: [
{name: "latest", url: "https://example.com/feed"},
],
};const feedList = {
exampleSite: [
{name: "latest", url: "https://example.com/feed"},
],
};
copy
これで読みたい記事の登録が完了しました。
他にも読みたい記事を増やしたい場合は、以下のように、フィードURLを調べて、サイト名(名称は任意でok)とフィード名(名称は任意でok)とフィードURLを入力します。
const feedList = {
exampleSite: [
{name: "latest", url: "https://example.com/feed"},
],
サイト名: [
{name: "フィード名", url: "フィードURL"},
],
};const feedList = {
exampleSite: [
{name: "latest", url: "https://example.com/feed"},
],
サイト名: [
{name: "フィード名", url: "フィードURL"},
],
};
copy
サイトによっては、特定のカテゴリーの記事のフィードなど複数のフィードを提供している場合があります。
その場合は以下のように入力すれば、同じサイトで複数のフィードの記事を登録することができます。
const feedList = {
サイト名: [
{name: "フィード名1", url: "フィードURL1"},
{name: "フィード名2", url: "フィードURL2"},
],
};const feedList = {
サイト名: [
{name: "フィード名1", url: "フィードURL1"},
{name: "フィード名2", url: "フィードURL2"},
],
};
copy
2つのサイトの記事(1つは最新記事のみで、もう1つは最新記事とITカテゴリーの最新記事)を受け取りたい場合の例です。
const feedList = {
exampleSite1: [
{name: "latest", url: "https://example.com/feed1"},
],
exampleSite2: [
{name: "latest", url: "https://example.com/feed2"},
{name: "it", url: "https://example.com/it/feed2"},
],
};
const feedList = {
exampleSite1: [
{name: "latest", url: "https://example.com/feed1"},
],
exampleSite2: [
{name: "latest", url: "https://example.com/feed2"},
{name: "it", url: "https://example.com/it/feed2"},
],
};
copy
上記形式で、読みたい記事を登録できたら、それをファイルにコピペします。
Macユーザーは「command + s」、Windowsユーザーは「ctrl + s」でファイルを保存します。
3. 登録した記事をGmailに送信する
まず、「コード」というファイルの名前を「main」に変更しましょう。
そして、以下のコードをmainファイルにコピペします。
function sendTargetArticleToGmail() {
try {
// 送信したい記事を指定する
const feedUrls = [
getFeedUrl("xxx", "xxx"),
getFeedUrl("xxx", "xxx"),
getFeedUrl("xxx", "xxx"),
];
// 送信したい記事の件数
const articleCount = 10;
// 記事を送信したいメールアドレスを指定
const recipient = "xxx@gmail.com";
// 件名
const subject = "各フィードの記事";
// メール本文
let emailBody = "";
feedUrls.forEach((feedUrl) => {
emailBody += `# フィードURL: ${feedUrl}\n\n`;
// XMLのルート要素を取得
const response = UrlFetchApp.fetch(feedUrl);
const xml = XmlService.parse(response.getContentText());
const root = xml.getRootElement();
// 記事の取得
const articles = getArticle(root, articleCount);
// 記事がない場合
if (articles.length === 0) {
emailBody += "記事が見つかりませんでした。\n\n";
return;
}
// メール本文に記事のタイトルとリンクを追記
const articleTitleAndLink = articles.map(item => `## ${item.title}\n${item.link}`).join("\n\n");
emailBody += articleTitleAndLink;
emailBody += "\n\n--------------------------------------------\n\n";
});
GmailApp.sendEmail(recipient, subject, emailBody);
Logger.log("メールが正常に送信されました。");
} catch (e) {
Logger.log(e.message);
}
}
function getFeedUrl(site, name) {
const feeds = feedList[site];
if (!feeds) {
throw new Error(`サイト'${site}'が存在しません。`);
}
const feed = feeds.find(feed => feed.name === name);
if (!feed) {
throw new Error(`'${name}'のフィードが、サイト'${site}'に存在しません。`);
}
return feed.url;
}
function getArticle(xmlRoot, articleCount) {
if (xmlRoot.getName() === "feed") {
// Atom形式の場合
const entries = xmlRoot.getChildren("entry", xmlRoot.getNamespace()).slice(0, articleCount);
return getAtomArticleTitleAndLink(xmlRoot, entries);
} else if (xmlRoot.getName() === "rss") {
// RSS形式の場合
const entries = xmlRoot.getChild("channel").getChildren("item").slice(0, articleCount);;
return getRssArticleTitleAndLink(entries);
}
return [];
}
function getAtomArticleTitleAndLink(xmlRoot, entries) {
const articleTitleAndLinkList = [];
entries.forEach((entry) => {
try {
// Atom形式のタイトルとリンク
const titleElement = entry.getChild("title", xmlRoot.getNamespace());
const linkElement = entry.getChild("link", xmlRoot.getNamespace());
const title = titleElement ? titleElement.getText() : "タイトル不明";
const link = linkElement
? linkElement.getAttribute("href").getValue()
: "リンク不明";
articleTitleAndLinkList.push({title, link});
} catch (e) {
Logger.log(e.message);
}
})
return articleTitleAndLinkList;
}
function getRssArticleTitleAndLink(entries) {
const articleTitleAndLinkList = [];
entries.forEach((entry) => {
try {
// RSS形式のタイトルとリンク
const titleElement = entry.getChild("title");
const linkElement = entry.getChild("link");
const title = titleElement ? titleElement.getText() : "タイトル不明";
const link = linkElement ? linkElement.getText() : "リンク不明";
articleTitleAndLinkList.push({title, link});
} catch (e) {
Logger.log(e.message);
}
})
return articleTitleAndLinkList;
}
function sendTargetArticleToGmail() {
try {
// 送信したい記事を指定する
const feedUrls = [
getFeedUrl("xxx", "xxx"),
getFeedUrl("xxx", "xxx"),
getFeedUrl("xxx", "xxx"),
];
// 送信したい記事の件数
const articleCount = 10;
// 記事を送信したいメールアドレスを指定
const recipient = "xxx@gmail.com";
// 件名
const subject = "各フィードの記事";
// メール本文
let emailBody = "";
feedUrls.forEach((feedUrl) => {
emailBody += `# フィードURL: ${feedUrl}\n\n`;
// XMLのルート要素を取得
const response = UrlFetchApp.fetch(feedUrl);
const xml = XmlService.parse(response.getContentText());
const root = xml.getRootElement();
// 記事の取得
const articles = getArticle(root, articleCount);
// 記事がない場合
if (articles.length === 0) {
emailBody += "記事が見つかりませんでした。\n\n";
return;
}
// メール本文に記事のタイトルとリンクを追記
const articleTitleAndLink = articles.map(item => `## ${item.title}\n${item.link}`).join("\n\n");
emailBody += articleTitleAndLink;
emailBody += "\n\n--------------------------------------------\n\n";
});
GmailApp.sendEmail(recipient, subject, emailBody);
Logger.log("メールが正常に送信されました。");
} catch (e) {
Logger.log(e.message);
}
}
function getFeedUrl(site, name) {
const feeds = feedList[site];
if (!feeds) {
throw new Error(`サイト'${site}'が存在しません。`);
}
const feed = feeds.find(feed => feed.name === name);
if (!feed) {
throw new Error(`'${name}'のフィードが、サイト'${site}'に存在しません。`);
}
return feed.url;
}
function getArticle(xmlRoot, articleCount) {
if (xmlRoot.getName() === "feed") {
// Atom形式の場合
const entries = xmlRoot.getChildren("entry", xmlRoot.getNamespace()).slice(0, articleCount);
return getAtomArticleTitleAndLink(xmlRoot, entries);
} else if (xmlRoot.getName() === "rss") {
// RSS形式の場合
const entries = xmlRoot.getChild("channel").getChildren("item").slice(0, articleCount);;
return getRssArticleTitleAndLink(entries);
}
return [];
}
function getAtomArticleTitleAndLink(xmlRoot, entries) {
const articleTitleAndLinkList = [];
entries.forEach((entry) => {
try {
// Atom形式のタイトルとリンク
const titleElement = entry.getChild("title", xmlRoot.getNamespace());
const linkElement = entry.getChild("link", xmlRoot.getNamespace());
const title = titleElement ? titleElement.getText() : "タイトル不明";
const link = linkElement
? linkElement.getAttribute("href").getValue()
: "リンク不明";
articleTitleAndLinkList.push({title, link});
} catch (e) {
Logger.log(e.message);
}
})
return articleTitleAndLinkList;
}
function getRssArticleTitleAndLink(entries) {
const articleTitleAndLinkList = [];
entries.forEach((entry) => {
try {
// RSS形式のタイトルとリンク
const titleElement = entry.getChild("title");
const linkElement = entry.getChild("link");
const title = titleElement ? titleElement.getText() : "タイトル不明";
const link = linkElement ? linkElement.getText() : "リンク不明";
articleTitleAndLinkList.push({title, link});
} catch (e) {
Logger.log(e.message);
}
})
return articleTitleAndLinkList;
}
copy
ソースコードの内容について概要を説明します。(興味のある方だけ読んでください)
・まずは、送信したい記事と件数、メールアドレス、件名を指定
・次に、フィードURLからXMLのルート要素を取得
・そのルート要素をもとに、フィードがAtom形式かRSS形式かを判別して、各形式の取得方法で、各記事のタイトルとURLを取得
・取得した記事のタイトルとURLをメール本文に書き込み、指定したメールアドレスにメールを送信
では、自分が読みたい記事を自分宛に送信できるように、ソースコードをちょっと修正します。簡単な修正です。
送信したい記事と件数、メールアドレス、件名の指定
mainファイルの3~17行目が修正箇所です。
送信したい記事の指定方法は、以下のように、feedListファイルに登録したフィードのサイト名とフィード名を入力します。
// 送信したい記事を指定する
const feedUrls = [
// この中に以下の形式で読みたい記事を指定する
getFeedUrl("サイト名", "フィード名"),
getFeedUrl("サイト名", "フィード名"),
getFeedUrl("サイト名", "フィード名"),
];// 送信したい記事を指定する
const feedUrls = [
// この中に以下の形式で読みたい記事を指定する
getFeedUrl("サイト名", "フィード名"),
getFeedUrl("サイト名", "フィード名"),
getFeedUrl("サイト名", "フィード名"),
];
copy
サイト名とフィード名は、feedListファイルのこの部分です。
const feedList = {
サイト名: [
{name: "フィード名", url: "フィードURL"},
],
サイト名: [
{name: "フィード名", url: "フィードURL"},
{name: "フィード名", url: "フィードURL"},
],
};const feedList = {
サイト名: [
{name: "フィード名", url: "フィードURL"},
],
サイト名: [
{name: "フィード名", url: "フィードURL"},
{name: "フィード名", url: "フィードURL"},
],
};
copy
例えば、feedListファイルの内容が以下の場合は、
const feedList = {
exampleSite1: [
{name: "latest", url: "https://example.com/feed1"},
],
exampleSite2: [
{name: "latest", url: "https://example.com/feed2"},
{name: "it", url: "https://example.com/it/feed2"},
],
};
const feedList = {
exampleSite1: [
{name: "latest", url: "https://example.com/feed1"},
],
exampleSite2: [
{name: "latest", url: "https://example.com/feed2"},
{name: "it", url: "https://example.com/it/feed2"},
],
};
copy
以下のように指定すればokです。
// 送信したい記事を指定する
const feedUrls = [
getFeedUrl("exampleSite1", "latest"),
getFeedUrl("exampleSite2", "latest"),
getFeedUrl("exampleSite2", "it"),
];// 送信したい記事を指定する
const feedUrls = [
getFeedUrl("exampleSite1", "latest"),
getFeedUrl("exampleSite2", "latest"),
getFeedUrl("exampleSite2", "it"),
];
copy
記事の送信件数については、以下の数字を修正します。以下だと、指定した記事が10件ずつ送信されるようになります。
// 送信したい記事の件数
const articleCount = 10;// 送信したい記事の件数
const articleCount = 10;
copy
宛先は、以下のxxxにご自身のメールアドレスを入力します。
件名は、以下の「各フィードの記事」の部分を、受け取りたい件名で修正します。
// 記事を送信したいメールアドレスを指定
const recipient = "xxx@gmail.com";
// 件名
const subject = "各フィードの記事";// 記事を送信したいメールアドレスを指定
const recipient = "xxx@gmail.com";
// 件名
const subject = "各フィードの記事";
copy
これで、読みたい記事を自分のメールアドレスに送信できるようになりました。
ファイルの編集は終わりなので、ファイルをMacユーザーは「command + s」、Windowsユーザーは「ctrl + s」で保存します。
記事をGmailに送信できるかテストしましょう。
以下の「実行」ボタンを押下します。(実行ボタンの右横がsendTargetArticleToGmail になっていることを確認してください)
すると、以下のポップアップが表示されるので、「権限を確認」ボタンを押下して、ご自身のGoogleアカウントでログインします。
以下の警告が出るので、「詳細」を押下して、「記事をGmailに送信するスクリプトに移動」を押下して、スクリプトのGoogleアカウントへのアクセス(Gmailのアクセス)リクエストが問題がないことを確認して、許可します。
実行ログが表示されるので、「メールが正常に送信されました。」と表示されたら、実行成功です。
あなたのメールアドレスに読みたい記事が送信されています。
4. 毎日指定の時間に記事が送信されるようにする
最後の手順です。
毎日指定の時間にスクリプトを自動実行して、記事がGmailに送信されるように設定します。
サイドメニューの「トリガー」ボタンを押下します。
以下の画面右下の「+ トリガーを追加」ボタンを押下します。
以下のように設定して保存すると、毎日7:00-8:00の時間帯に記事が送信されるようになります。ご自身にあわせて内容を入力してください。
以下のように表示されたら設定完了です。
さいごに
毎朝記事を読む習慣を作りたいと思い、「仕事やプライベートで毎日のように使うGmailに記事が送信されたら、読む習慣ができそう」ということで今回のスクリプトを作成しました!
このスクリプトが、少しでもあなたの役に立ってくれたら嬉しく思います!
さいごに、dotDでは一緒に働く仲間を募集しています。
興味のある方はぜひご連絡いただけると嬉しいです!!!