📅

Outlook予定表のスケジュールをサーバーレスで取得する(AWS Lambda + Ruby)

2023/11/27に公開

弊社ではスケジュールの管理にOutlook予定表を使用しています。
Outlookと連携した社内システムも多くあるのですが、これまで実際に自分でOutlook予定表と連携する機能を実装したことがありませんでした。

近々、Outlook予定表を利用したシステムを開発する機会があり、かつそれをサーバーレス上で実行する予定です。
システムを開発する前に、お試しでOutlook予定表の読み出しを実装してみました。

作ったもの

AWS Lambdaを1分周期で実行し、その日の予定をOutlook予定表から読み出して、標準出力するというシンプルなものです。

読み出す周期やトリガを変更したり、出力先を標準出力ではなく別システム等にしたりすることで、予定表を様々な場面で活用できるはずです。
ソースコードは以下のリポジトリにて公開しています。

https://github.com/yuuu/outlook-schedule-fetcher-sample

今回実装したのは読み出しのみで、書き込みは対象外としています。

実装上のポイント

ここからは実装上のポイントとなった部分をご紹介します

Microsoft Entra ID(旧称 Azure Active Directory)へのアプリの登録

Azure Portalにログインし、「Microsoft Entra ID」→「アプリの登録」→「新規登録」の順で画面遷移して、アプリを登録します。
今回の用途だと、特別な設定は不要で、「名前」以外は全て既定値で問題ありませんでした。

続いて「証明書とシークレット」→「新しいクライアントシークレット」の順で画面遷移して、クライアントシークレットを作成します。作成後に表示されるシークレットの値が認証時に必要となるのでメモしておきましょう。

最後に「APIのアクセス許可」→「アクセス許可の追加」の順で画面遷移して、「Microsoft Graph」の「Calendars.Read」を追加します。組織の設定によってはここで管理者の許可が必要となることがあります。

Rubyのプログラムによるアクセストークンの取得

次のようなソースコードでアクセストークンを取得することができました。

def auth_azure(tenant_id, client_id, client_secret)
  url = "https://login.microsoftonline.com/#{tenant_id}/oauth2/v2.0/token"
  body = {
    scope: 'https://graph.microsoft.com/.default',
    grant_type: 'client_credentials',
    client_id:,
    client_secret:,
  }
  res = Faraday.post(url) do |req|
    req.headers['Content-Type'] = 'application/x-www-form-urlencoded'
    req.body = URI.encode_www_form(body)
  end

  JSON.parse(res.body)['access_token']
end

筆者が使い慣れているFaradayを使っていますが、HTTP Clientであれば他のものでも動作するはずです。

tenant_id client_id client_secret はAzure Portalにて確認した値を使用します。秘匿情報なのでこのようにAWS Lambdaの環境変数として入力すると良いです。

Outlook予定表の読み出し

次のようなソースコードでOutlook予定表を読み出すことができました。

def fetch_schedules(access_token, azure_user_principal_name)
  url = "https://graph.microsoft.com/v1.0/users/#{azure_user_principal_name}/calendar/calendarview" 
  res = Faraday.get(url) do |req|
    req.headers['Authorization'] = "Bearer #{access_token}"
    req.headers['Accept'] = 'application/json'
    req.headers['Prefer'] = "outlook.timezone=\"Asia/Tokyo\""
    req.params = {
      startDateTime: Date.today.to_time.iso8601,
      endDateTime: (Date.today + 1).to_time.iso8601,
      orderby: 'start/dateTime asc'
    }
  end

  JSON.parse(res.body)['value']
end

access_token は前述の手順で取得したものを使用します。
azure_user_principal_name は対象によっていろいろな指定方法があるようですが、今回の場合読み出したい対象のメールアドレスを指定することで取得ができました。(参考)

今回は orderby をしていることで、時系列順にソートされた状態で取得しています。
他にも様々なクエリパラメータを使用できるようですので、ドキュメントを見ながら適切なものを指定すると良いでしょう。

まとめ

なんとなく、Outlookとの連携は難しそうというイメージを持っていましたが、実際にやってみるとそこまで難しくはないことがわかりました。

Outlook予定表と連携することでアプリの可能性が拡がりますね。

GitHubで編集を提案
Fusic 技術ブログ

Discussion