6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GASで簡単!メール自動送信する方法

Last updated at Posted at 2025-01-28

簡単にスケジュールをお知らせしてくれるツールを作ろう!

こんにちは、ちょも です。
みなさん、普段のスケジュール管理はどうしていますか?
私はGoogleカレンダーを使っているのですが、ついつい予定を入れたまま放置してしまいがちです。
その結果、ダブルブッキングや予定の見落としがよくあり、もう少しスケジュールの管理を楽にできないかと考えました。
そこで、Googleカレンダーの予定を毎日メールで通知してくれるスクリプトを作成しましたので、その手順をご紹介します。


● 使用したツール


1 まずはChatGPTに尋ねる

全くの素人が一から作るのは無理な話なので、ChatGPTに尋ねます。。

ChatGPT1.png


javascript
function sendSchedule() {
    // 今日の予定を取得
    var events = CalendarApp.getDefaultCalendar().getEventsForDay(new Date());
    
    // メールを送信
    MailApp.sendEmail({
        to: "your-email@example.com",  // メールアドレスを入力
        subject: "今日のスケジュール",
        body: "今日の予定は以下の通りです:\n" + events.map(function(event) {
            return event.getTitle() + " - " + event.getStartTime();
        }).join("\n")
    });
}

パパッとコードが出てきました。 見慣れないコードですが、解説が付いているのでなんとか読めます。 気になる点が your-email@example.com, // メールアドレスを入力 このコードに送信先アドレスを入力するということ。

今後送信先が増えることも考慮して、Googleスプレッドシートを使いたいです。
それも尋ねます。


ChatGPT2.png


説明を読んで指示通り進めます。


ChatGPT7.png


スプレッドシートもできました。
サンプルなのでとてもシンプルですが、これでいつでも増やすことも減らすことも可能になります。
試しにテストメールを送ります。


2 3日分のスケジュール・タスク・レイアウトを変える。

無事メールを受信することができました。
更に必要な事項を増やします。

① 今日・明日・明後日の3日間の予定を入れる

② タスクを入れる

③ 表示方法を変える

①はChatGPTが教えてくれた通りにコードを追加して完了し、③はコードの補足を読み時ながら見当を付け聞かなくてもできました。


問題は②です。


ChatGPT3.png


Googleスプレッドシートに入力する方法でした。
これではスプレッドシートに入力する手間が発生してしまいます。


私は楽をしたい。


Googleカレンダーのタスクを入れたかったので、聞き方を変えました。


ChatGPT4.png
 

意味が分からない・・・。
そこはChatGPT。遠慮無くお願いを続けました。

ChatGPT5.png



ここからが地獄の始まりでした。



教えてもらった方法で設定してもなかなか上手くタスクが紐付けされず、質問の嵐です。
ずっとGoogle Apps Scriptとコンソール内を往復し、いじり倒しました。
何十回と質問していたらこんな表示になりました。

ChatGPT6.png




「もう使えないの!?(私を見捨てるの!?)」


という気持ちです。
しかしよく読むと違うタイプのChatGPTがお返事をしてくれるようです。
GPT-4o miniならFreeで無制限のようです。自分が何を使っているのかすら知らなかったです。
取り敢えず安心して進み、なんとか完成!


完成コード(長いので折りたたみ)
// 今日・明日・明後日のGoogleカレンダー予定とGoogleタスクをまとめてメール送信
function sendThreeDaysAgendaAndTasks() {
  // === 1. スプレッドシートからメールアドレスを取得 ===
  const sheetId = "●●●●"; // スプレッドシートのID
  const sheet = SpreadsheetApp.openById(sheetId).getSheetByName("●●●●"); // シート名を指定
  const emailRange = sheet.getRange("A:A"); // メールアドレスが入力されている列
  const emailValues = emailRange.getValues().flat().filter(email => email.includes("@")); // メールアドレスだけ取得

  if (emailValues.length === 0) {
    Logger.log("メールアドレスが見つかりませんでした");
    return;
  }

  // === 2. カレンダーとタスクの情報を取得 ===
  const today = new Date(); // 今日
  const tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000); // 明日
  const dayAfterTomorrow = new Date(today.getTime() + 2 * 24 * 60 * 60 * 1000); // 明後日

  // 今日・明日・明後日の予定を取得
  const calendarMessages = [
    getCalendarEventsForDate(today, "今日", formatDate(today)),
    getCalendarEventsForDate(tomorrow, "明日", formatDate(tomorrow)),
    getCalendarEventsForDate(dayAfterTomorrow, "明後日", formatDate(dayAfterTomorrow))
  ];

  // 今日・明日・明後日のタスクを取得
  const taskMessages = getGoogleTasksForThreeDays();

  // メール本文を作成
  const emailMessage = `
${calendarMessages[0]}
【今日のタスク】
${taskMessages["今日"]}

===============================

${calendarMessages[1]}
【明日のタスク】
${taskMessages["明日"]}

===============================

${calendarMessages[2]}
【明後日のタスク】
${taskMessages["明後日"]}
===============================
`;

  // === 3. メールを送信 ===
  emailValues.forEach(email => {
    GmailApp.sendEmail(email, "今後3日間の予定とタスク", emailMessage);
  });

  Logger.log("メール送信完了");
}

// 特定の日付のGoogleカレンダー予定を取得
function getCalendarEventsForDate(date, label, formattedDate) {
  const startOfDay = new Date(date.getFullYear(), date.getMonth(), date.getDate());
  const endOfDay = new Date(startOfDay.getTime() + 24 * 60 * 60 * 1000 - 1);

  const calendar = CalendarApp.getDefaultCalendar();
  const events = calendar.getEvents(startOfDay, endOfDay);

  let message = `【${label}の予定 (${formattedDate})】\n`;
  if (events.length === 0) {
    message += "予定はありません。\n\n";
  } else {
    events.forEach(event => {
      const title = event.getTitle();
      const startTime = event.getStartTime();
      const endTime = event.getEndTime();
      const description = event.getDescription();  // イベントの詳細を取得

      message += `・${title}\n  時間: ${startTime.toLocaleTimeString()} ~ ${endTime.toLocaleTimeString()}\n`;
      if (description) {
        message += `  詳細: ${description}\n`;  // 詳細がある場合に表示
      }
      message += "\n";
    });
  }

  return message;
}

// Googleタスクを取得し、3日分にフィルタリング
function getGoogleTasksForThreeDays() {
  const tasksService = Tasks.Tasks.list('@default', {
    showCompleted: false // 完了済みタスクは除外
  });

  const today = new Date();
  const tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000); // 明日
  const dayAfterTomorrow = new Date(today.getTime() + 2 * 24 * 60 * 60 * 1000); // 明後日

  let todayTasks = [];
  let tomorrowTasks = [];
  let dayAfterTomorrowTasks = [];

  // タスクを分類
  if (tasksService.items && tasksService.items.length > 0) {
    tasksService.items.forEach(task => {
      const dueDate = task.due ? new Date(task.due) : null;

      if (dueDate) {
        // 今日のタスク
        if (isSameDay(dueDate, today)) {
          todayTasks.push(`・${task.title}(締切: ${dueDate.toLocaleDateString()})`);
        }
        // 明日のタスク
        else if (isSameDay(dueDate, tomorrow)) {
          tomorrowTasks.push(`・${task.title}(締切: ${dueDate.toLocaleDateString()})`);
        }
        // 明後日のタスク
        else if (isSameDay(dueDate, dayAfterTomorrow)) {
          dayAfterTomorrowTasks.push(`・${task.title}(締切: ${dueDate.toLocaleDateString()})`);
        }
      }
    });
  }

  let tasksMessage = {
    "今日": todayTasks.length > 0 ? todayTasks.join("\n") : "今日のタスクはありません。",
    "明日": tomorrowTasks.length > 0 ? tomorrowTasks.join("\n") : "明日のタスクはありません。",
    "明後日": dayAfterTomorrowTasks.length > 0 ? dayAfterTomorrowTasks.join("\n") : "明後日のタスクはありません。"
  };

  return tasksMessage;
}

// 日付を「MM/dd」の形式で整形するヘルパー関数
function formatDate(date) {
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  return `${month}/${day}`;
}

// 2つの日付が同じ日かどうかをチェックするヘルパー関数
function isSameDay(date1, date2) {
  return date1.getFullYear() === date2.getFullYear() &&
         date1.getMonth() === date2.getMonth() &&
         date1.getDate() === date2.getDate();
}



正直コードの解読は完璧にはできていません。
ただここで何をしているがなんとなく分かる程度です。

● メール受信を確認する。

紆余曲折し、ChatGPTとの付き合い方が分からい時がありましたが実際に使ってみます。


↑は元となるカレンダーです。


↑実際のメール受信画像です。


私のお見苦しいカレンダー画像ですみません。
このスケジュールを2つのメールアドレス宛に送信設定致しました。
実際に2つのアドレスに送信されております。
当日のスケジュール・タスクともに時間と詳細を表示し、スケジュールを確認しなくても3日間の予定がシンプルに分かります。

実際に使ってみての感想

このスクリプトを使ってみて、非常に便利だと感じました。
これまでは入力して満足し、確認することを怠ってしまい当日焦ることがありましたが、使い始めて毎日メールで通知されることで忘れずにチェックできるようになりましたし、スケジュールの詳細入力にも注意するようにもなりました。
今後はもっと業務上のスケジュールやタスクを入力していくので、改善する点があれば随時変更していきます。

● (補足)ChatGPTを使って感じたこと

ChatGPTを使ってみて良かったこと
・ここまでやったことはほぼコピー&ペーストで作業が楽
・長文でも理解してくれる
・チャットを始めるときに「分かりやすく説明して」とお願いしておくと、終わるまで丁寧な回答を得られる。

ChatGPTの難しいところ
・会話をでできる限り分かりやすく伝えることが大変で難しかった
・何かエラーになった時、原因になり得るものは自ら伝えないと無限ループ
・情報が最新では無い場合があるので、HP上のレイアウトが変わってしまうとたどり着けない
 (これのことですか?と聞けば合ってるかどうかは教えてくれる)


作業は凄く単純で、コードを全く知らなくても時間を掛ければそれなりのものは完成できました。 ChatGPTを使わない状況で今回のツールを作ろうとしたら間違いなく頓挫しています。

質問に対し答えてくれるし、アドバイスもしてくれる。
ドラえもんを手に入れたような気持ちです:smiley:

ChatGPTはドラえもんのように感情はなく、機械的(ドラえもんもロボットですが)で融通が利かないところがありますが、会話次第で無限の可能性があると感じました。

ChatGPTを使ってコードを駆使し、様々なツールのヒントにしようと思っていました。
しかし今はまだChatGPTに教えてもらったことの理解がしきれず、とても時間が掛かってしまいます。
現在思案中のものがあるので、どんな風に作るのかChatGPTに質問をしながら作りたいと思います。


6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?