見出し画像

オフィスへの来訪申請をGoogleカレンダーと連携させて自動化してみたよ

みなさん自動化してますか。こんにちは!エンジニアのオギーです。
今回は少し「お出かけ」とは関係ないですが、面倒な来訪申請をGoogleカレンダーと連携させることで自動化するシステムを最近作ってみたので、紹介させて頂きます!

背景

弊社は最近表参道のマンションオフィスから大崎にあるセガサミーさんシェアオフィスに移転しました。こちらのオフィスは非常におしゃれかつ食堂もあり良い感じです!ただ出来たばかりのシェアオフィスということで、いくつか不便な点があり、その中でも「来訪申請」が非常に面倒で頭を悩ませていました。来訪申請を行うためには

- 申請書(Wordファイル)に来訪者の名前やメールアドレス、日時などを入力する
- メールにその申請書を添付し受付に送信する

を毎回行う必要があります*1。申請自体は簡単ですが、弊社は業務委託の方やアルバイト・インターン生の方々も多くいるため一々手動で申請していては、本業に支障が出るほど面倒かつ忘れてしまいます。もし忘れてしまうと来訪者がオフィスに入ることができずに多大な迷惑をかけてしまう恐れがあるため何とかする必要がありました。

作ったもの

この問題を解決するために、以下のようなシステムを1日ほどで構築してみました。これらの処理はすべてPythonで書き、Digdagでスケジュール管理しています。

1. Googleカレンダーから次の日の来訪予定者を自動で取得する
2. 来訪者の情報を申請書(ワードファイル)に自動で記載する
3. 申請書をメールに添付し、自動で送信する
4. Slackに申請内容を通知する

このシステムにより、Googleカレンダーに来訪予定を記載するだけで自動で申請が行われるようになりました。今回実装したPythonスクリプトのサンプル ノートブックをGithub上にて公開してみましたので、ぜひ参考にしてみてください。

0. GoogleカレンダーAPIのセットアップ

まずはじめにGoogleカレンダーからデータを取得するために以下のような設定が必要です。

1. Google Cloud Consoleから"Google Calendar API "を有効にする
2. サービスアカウントを作成する
3. サービスアカウントに対してGoogleカレンダーの閲覧権限を付与する

具体的な設定内容については、箇条書きにて記載しておきます。

APIの有効とサービスアカウントの作成
https://console.cloud.google.com/apis/library を開き, "Google Calender API" を検索し, "有効"にする
- 次に左タブの"認証情報"を選択し, 上部の"認証情報を作成"を選択する
- 以下のような設定でサービスアカウントを作成する
  - 使用するAPI: "Google Calender API"
  - APIを呼び出す場所: "その他の非UI(cronジョブ、デーモンなど)"
  - アクセスするデータの種類: "アプリケーションデータ"
  - App Engineまたは...? : "いいえ、使用しません"

Googleカレンダーの閲覧権限の付与
- Googleカレンダーの右上のクルクルを選択し"設定"を選択する
- "他のカレンダーの設定"から取得したいカレンダーを選択する
- "特定のユーザーとの共有"にて作成したサービスアカウントのメールアドレスを追加, 権限を付与する

ここまで設定することで準備は完了です。次にPythonを用いて実際にGoogleカレンダーからデータを取得してみます。

1. Googleカレンダーからカレンダー情報を取得する

GoogleカレンダーAPIをPythonを用いて使用する場合、以下の公式のライブラリを使用することができます。

これらのライブラリを用いて以下のような形で認証することで、簡単にGoogleカレンダーからデータを取得することができます

from googleapiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials

GOOGLE_OAUTH_SERVICE_ACCOUNT_PRIVATE_KEY_PATH = 'google_oauth.json' # credentialsが記載されたjsonのパスを指定する
GOOGLE_CALENDER_ID = '' # データを取得したいGoogleカレンダーのIDを指定する
GOOGLE_CALENDER_SCOPES = ['https://www.googleapis.com/auth/calendar.readonly'] # read権限のみ付与する

# データを取得
calendar_service = build('calendar', 'v3', http=google_http_auth, cache_discovery=False)

events_result = calendar_service.events().list(
    calendarId=GOOGLE_CALENDER_ID,
    timeMin=datetime.datetime.now(timezone('Asia/Tokyo')).isoformat(),
    timeMax=(datetime.datetime.now(timezone('Asia/Tokyo')) + datetime.timedelta(days=3)).isoformat(),
    orderBy='startTime',
    singleEvents=True,
).execute()
events_result.get('items', [])
# 期限内にデータが存在していた場合はjsonが返ってきます

次に名前や日時などをGoogleカレンダーから正確に取得するために、予めフォーマットを定義します。今回は以下のような形に定義しました。

<来社予定の方のニックネーム>出社<来客時間(hour)>-<終了時間(hour)>
例. オギー出社10-18.5

このような形でGoogleカレンダーに記載しておくことで、正規表現によりそれぞれ要素を分割して使用することができるようになります。

2.  ワードファイルに内容を記載する

次にGoogleカレンダーから取得した内容を直接docxファイルに記載してみます。こちらも既に便利なライブラリが公開されているので、使ってみます。

以下のようなテーブルが一つあるdocxファイルに対して、テーブル内にテキストを書き込んでみます。

下記スクリプトのように、「テーブルを指定する -> セルを指定する -> その中に値を代入する」といった直感的な形で実装することができます。

VISIT_APPLICATION_DOCX_PATH = 'visit_application.docx' # 値を書き込みたいdocxファイルのパスを指定する
SUBMIT_APPLICATION_DOCX_PATH = 'submit_visit_application.docx' # 書き込んだdocxファイルの保存先を指定する

EXAMPLES = [
    {'name': 'テスト 太郎', 'name_kana': 'テスト タロウ', 'company_name': 'ホリデー株式会社', 'email': 'test@test.com'},
    {'name': '荻原 タロウ', 'name_kana': 'オギワラ タロウ', 'company_name': 'ホリデー株式会社', 'email': 'test_ogiwara@test.com'}
]

# wordをロードする
document = Document(VISIT_APPLICATION_DOCX_PATH)
# word内の一つ目のテーブルを指定する
docx_table = document.tables[0]

for i, example in enumerate(EXAMPLES):
    # テーブルのi行目を指定する
    row = docx_table.rows[i + 1]

    # 各行のセルに値を書き込んでいくよ
    row.cells[0].text = '05/01'
    row.cells[1].text = '10:00'
    row.cells[2].text = example['company_name']
    row.cells[3].text = example['name']
    row.cells[4].text = example['name_kana']
    row.cells[5].text = example['email']

# 書き込み終わったら新しいファイル名で保存する
document.save(SUBMIT_APPLICATION_DOCX_PATH)

こんな形で意図した場所に書き込まれています。簡単ですね!

3. 申請書をメールに添付し、自動で送信する

提出するワードファイルを作成したら、最後にメールに添付し提出してみます。Pythonによるメールの送信するメソッドはデフォルトで準備されているため、ライブラリ等の必要はありません。今回はメール送信元もGmailアカウントを用いて行なっていきますが、その際 "安全性の低いアプリへのアクセスを許可する" 設定を行う必要があります。公式サイトなどを参考にして自己責任で設定してみてください。

まずは変数に値を設定しておきます (空の部分に自身のアカウント情報やカレンダーの情報を設定してください)

# GMAILを使ってメールを送信してみる
GMAIL_HOST = 'smtp.gmail.com'
GMAIL_PORT = 587

# 使用するGMAILアカウントのID, PASSWORDを入力する
GMAIL_USERNAME = ''
GMAIL_PASSWORD = ''

# 使用するGMAILのアドレスを入力する (送信元)
FROM_ADDRESS = ''
# 送信先のメールアドレスを入力する
TO_ADDRESS = ''

# メールの件名
MESSAGE_SUBJECT = ''
# メールの本文
MESSAGE_BODY = ''

# 上記で作成したワードファイルを指定してみる
attachment_file_path = SUBMIT_APPLICATION_DOCX_PATH 
attachment_file_name = 'submit_visit_application.docx'

次にメッセージを生成します。

# メール用のメッセージを作成する
message = MIMEMultipart()
message['Subject'] = MESSAGE_SUBJECT # 件名
message['From'] = FROM_ADDRESS # 送信元メールアドレス
message['To'] = TO_ADDRESS # 送信先メールアドレス
message.attach(MIMEText(MESSAGE_BODY, 'plain'))  # 本文

# ファイルを添付する
part = MIMEBase('application', "octet-stream")
part.set_payload(open(attachment_file_path, "rb").read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="{}"'.format(attachment_file_name))
message.attach(part)

最後に生成したメッセージを送信します。

# メールを送信する

# SMTPのセットアップ
smtp = smtplib.SMTP(GMAIL_HOST, GMAIL_PORT)
smtp.ehlo()
smtp.starttls()
smtp.ehlo()

# GMAILにログインする
smtp.login(GMAIL_USERNAME, GMAIL_PASSWORD)
# メールを送信
smtp.sendmail(FROM_ADDRESS, TO_ADDRESS, message.as_string())
# SMTPを閉じる
smtp.quit()

このような形でファイルを添付したメールを送信することができます。
簡単ですね!!最後に依頼が正しく行われたかを誰もが確認できるようにSlackに通知するようにしておきました。(エラーが起こった場合も同様にSlackで通知するようにしています)

今後の展望

今回は来訪申請の自動化というテーマでシステムを構築しましたが、課題点がいくつかあります。例えばGoogleカレンダーに記載するフォーマットを予め定義しましたが、この時点ではバリデーションを行うことができないため、間違ったフォーマットであったり変な文字列が入っていたりする場合は正しく申請を行うことができません。申請の他に監視君を1時間に1回動かすことで早い段階でミスに気づかせることはできるかもしれませんが、本質的ではなさそうな気がしています。

そこで近々 以下のようにSlack上からも申請が行えるような仕組みも構築し、何か間違えて申請が行えてなかった場合もすぐにSlack上で行えるようなシステムを構築していきたいと思っています。

"/tunnel 来訪申請 10:00 荻原 崇 オギワラ タカシ takashi@test.com"

(こんな形でSlack上に記載するだけで申請できたらもっと楽になりそうな予感です。)こちらも完成したらブログに書きますね:)

まとめ

今回はGoogleカレンダーとの連携による来訪申請自動化システムについてお話しました。弊社は少数精鋭のためルーティン化されたタスクや不毛なタスクは極力自動化することで本業に集中できるような仕組み・環境を今後も積極的に作っていきたいと思っています。

採用にも力を入れているので、気になった方はぜひチェックしてみて下さい!

*1 現在システム開発中とのことです。

この記事が気に入ったらサポートをしてみませんか?