LINE Messaging API × AWSサーバーレスによる定期メッセージ配信の設計と実装の要点

2026年4月17日
AWS
LINE Messaging APIとAWSサーバーレスによる定期メッセージ配信のイメージ

はじめに

企業がLINE公式アカウントを活用して顧客向けに情報配信する際、ユーザーごとにスケジュールされたタイミングでメッセージを送る要件は少なくありません。

LINE公式アカウントの標準機能だけでは、友だちごとに異なる曜日・頻度での定期配信は実現しにくく、LINE Messaging APIを組み合わせた実装が必要になります。

本記事では、AWSのサーバーレス構成(Lambda・EventBridge・DynamoDB)を用いた定期メッセージ配信の概要、LINE側・AWS側の設定の流れ、検証時の留意点を整理します。

本システムで実現できること

今回の構成により、次のような運用が可能です。

  • LINEビジネスアカウント(Messaging API)経由で、ユーザー単位にメッセージを送信する
  • 隔週・週1・複数曜日指定など、送信スケジュールを柔軟に設計する(EventBridgeのcronとDynamoDBの定義に依存)
  • 隔週・週1・複数曜日指定など、送信スケジュールを柔軟に設計する

標準のLINE公式アカウント機能では、友だち単位の定期配信に制約があるため、Messaging APIによるプッシュ送信を前提に設計します。

常設サーバー(EC2等)でAPIを常時稼働させるとコストと運用負荷が増えるため、本記事ではイベント駆動のサーバーレスで構築する方針とします。

システム構成と各コンポーネントの役割

想定する構成は次のとおりです。

  • AWS Lambda:LINE Messaging APIへHTTPリクエストを送信し、プッシュメッセージを配信
  • Amazon EventBridge:スケジュールルール(cron)でLambdaを定期起動
  • Amazon DynamoDB:ユーザーID・送信曜日・メッセージ内容などを格納し、Lambda起動時に参照
  • LINE公式アカウント:Messaging APIを有効化し、ユーザーから見れば当該アカウントからメッセージが届く
  • ユーザー:公式アカウントに友だち登録済みの配信対象

Lambdaは関数URL等のHTTPSエンドポイントを公開し、LINEからのWebhook受信と定期実行の両方に利用できる形が一般的です。

料金・運用上の留意点

小規模な利用人数(例:数十名規模)であれば、AWS側のLambda・DynamoDBの従量課金は月額数円程度に収まるケースが多いです。

一方、LINE公式アカウントのメッセージ送信枠はプランにより無料通数に上限があります。月200通を超える運用では有料プランへの切り替えが必要になる場合があります。最新の料金・枠はLINE公式の料金プランを必ず確認してください。

LINE料金プランのイメージ

構築の流れ(概要)

1. LINE Developersでチャネル作成、Messaging API有効化、アクセストークン取得
2. AWSでLambda(Python等)・DynamoDB・EventBridgeを構築
3. LambdaのエンドポイントをLINEのWebhook URLに登録
4. テスト送信およびスケジュール実行で動作確認

以下、LINE側とAWS側の要点を整理します。

LINE側の設定

アカウント・チャネル

LINEアカウント・チャネル設定のイメージ
  • 新規の場合はMessaging APIを選択してチャネルを作成します。
  • 既存アカウントの場合は、設定からMessaging APIを有効化します。
  • Channel IDChannel secretは後続の設定で使用するため、安全に保管します。

応答設定

LINE応答設定のイメージ

設定の「応答設定」で、Webhookを有効にします。チャットあいさつメッセージは、運用方針に応じて有効化します(認証済みアカウント等では不要な場合があります)。

アクセストークン

LINE Developersコンソールでプロバイダーとチャネルを選択し、チャネルアクセストークン(長期)を発行して保管します。Lambdaの環境変数等に設定します。

Webhook URL(Lambda構築後)

Lambdaのデプロイが完了し、関数URL等のHTTPSエンドポイントが確定したら、LINEの「Webhook URL」にそのURLを登録します。

AWS側の構築

Lambda

  • ランタイム例:Python 3.10
  • 依存ライブラリ:`requests` 等を利用する場合は、レイヤーまたはデプロイパッケージ(zip)に同梱してデプロイします。
  • 環境変数:チャネルアクセストークン、DynamoDBテーブル名などを設定します。
  • 関数URL:Webhook受信と疎通確認に利用できるようHTTPSを有効化します。

処理のイメージ

Webhookでユーザーからメッセージを受けた際にuserIdをログ出力し、定期実行時はDynamoDBをスキャンして翌日が送信対象の曜日に該当するユーザーへプッシュする、といった流れが取りやすいです。

import json
import requests
import boto3
import os
from datetime import datetime, timedelta

def lambda_handler(event, context):
    if 'body' in event:
        body = json.loads(event['body'])
    else:
        body = event

    if 'events' in body and body['events']:
        event_type = body['events'][0]['type']
        if event_type == 'message':
            user_id = body['events'][0]['source']['userId']
            print(f"User ID: {user_id} sent a message. Logging to CloudWatch.")
            print(f"Ignoring message event from user: {user_id}")
            return {
                'statusCode': 200,
                'body': json.dumps('Message event ignored')
            }

    return send_notifications()

def send_notifications():
    line_access_token = os.getenv('LINE_ACCESS_TOKEN')
    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.Table('xxxxx')

    response = table.scan()
    headers = {
        'Content-Type': 'application/json',
        'Authorization': f'Bearer {line_access_token}'
    }

    tomorrow = (datetime.now() + timedelta(days=1)).strftime('%a')
    print(f"Tomorrow is: {tomorrow}")

    for item in response['Items']:
        user_id = item['userID']
        day = item['Day']
        if day == tomorrow:
            payload = {
                'to': user_id,
                'messages': [{'type': 'text', 'text': 'message内容'}]
            }
            r = requests.post(
                "https://api.line.me/v2/bot/message/push",
                headers=headers,
                data=json.dumps(payload)
            )
            print(f"Sent message to {user_id}, response: {r.text}")

    return {
        'statusCode': 200,
        'body': json.dumps('Notifications sent successfully')
    }

テーブル名・メッセージ本文・曜日の表現は、運用要件に合わせて調整してください。

EventBridge

EventBridge設定のイメージ

スケジュールルールでcron式を指定し、日次など希望の時刻にLambdaを起動します。前日に「翌日分の通知」を送るロジックにする場合は、実行時刻とDynamoDBの曜日定義を整合させます。

DynamoDB

DynamoDB設定のイメージ

アクセス頻度が限定的であればオンデマンド課金が扱いやすいです。パーティションキー・属性は、`userID`・`Day`(送信対象曜日)・必要に応じて表示名などを格納します。

CloudWatch Logs

Lambdaの標準出力にuserIdを記録しておくと、ユーザーから一度メッセージを送ってもらい、ログと突き合わせてDynamoDB登録用のIDを特定しやすくなります。認証済みアカウント等でLINE側からIDが分かる場合は、この手順を省略できます。

動作確認と運用上の注意

Lambdaのテスト実行、またはEventBridgeによる定期実行で、意図したユーザーへプッシュが届くことを確認します。

参考:Webhookで受信するイベントの例

テキストメッセージ受信時は、LINEから次のようなJSONがPOSTされます(抜粋)。

{
  "destination": "xxxxxx",
  "events": [
    {
      "type": "message",
      "message": {
        "type": "text",
        "id": "xxxxxx",
        "text": "メッセージが入ります。"
      },
      "source": {
        "type": "user",
        "userId": "xxxxxx"
      }
    }
  ]
}

改善のヒント

現状のサンプルではテキストメッセージのイベントを無視する処理に留まっている場合、画像・スタンプ等のイベントでもWebhookが動き、意図しない分岐になることがあります。本番運用では、対象外のイベントタイプを明示的に無視する、またはreplyではなくpushのみに寄せるなど、仕様を固めたうえでコードを拡張してください。

まとめ

LINE Messaging APIとAWSサーバーレスを組み合わせることで、常設サーバーなしで定期配信の基盤を構築できます。コストはAWS側とLINE側の両方で発生するため、送信通数・運用体制・セキュリティ(トークン管理)をセットで設計することが、ビジネス利用では重要です。