Copyright© Mat Bao Company. All Reserved.
Sử dụng nội dung ở trang này và dịch vụ tại Mắt Bão có nghĩa là bạn đồng ý với Thỏa thuận sử dụng và Chính sách bảo mật của chúng tôi.
Công ty cổ phần Mắt Bão - Giấy phép kinh doanh số: 0302712571 cấp ngày 04/09/2002 bởi Sở Kế Hoạch và Đầu Tư Tp. Hồ Chí Minh.
Giấy phép cung cấp dịch vụ Viễn thông số 247/GP-CVT cấp ngày 08 tháng 05 năm 2018.
📢 Lưu ý: Bài viết mang tính chất tham khảo. Quý khách có thể tự điều chỉnh hoặc bổ sung thêm các tính năng khác theo nhu cầu sử dụng của mình.
1. Giới thiệu
Workflow “M365 Calendar → Teams – Nhắc lịch họp” giúp tự động gửi tin nhắn nhắc lịch vào nhóm chat Microsoft Teams khi một cuộc họp trong lịch Microsoft 365 (Outlook Calendar) còn khoảng 15 phút nữa là bắt đầu. Mỗi cuộc họp chỉ được nhắc 1 lần.
Workflow gồm 5 node:
- Schedule Trigger – chạy tự động mỗi phút.
- Microsoft Outlook Calendar – lấy các sự kiện bắt đầu trong 20 phút tới.
- Kiểm tra còn 15 phút (Code) – lọc cuộc họp còn ≤ 15 phút, bỏ qua cuộc họp đã hủy hoặc đã nhắc.
- Có cuộc họp cần nhắc? (IF) – chỉ đi tiếp khi có cuộc họp hợp lệ.
- Microsoft Teams – Gửi nhắc – gửi tin nhắn nhắc lịch vào nhóm chat Teams.

Hình 1: Tổng quan 5 node của workflow trong n8n
2. Chuẩn bị
- Đã import file JSON của workflow vào n8n (xem mục 8 nếu cần lấy lại mã JSON).
- Tài khoản Microsoft 365 có sử dụng Outlook Calendar và Microsoft Teams.
- Quyền truy cập Microsoft Entra ID (Azure Portal) để tạo App Registration (với n8n tự cài đặt – self-hosted).
- Một nhóm chat Teams dùng để nhận tin nhắc (tài khoản kết nối phải là thành viên nhóm chat này).
Ghi chú: Nếu Quý khách dùng n8n Cloud và trong cửa sổ tạo credential đã có sẵn nút Connect my account mà không yêu cầu Client ID/Client Secret, có thể bỏ qua Bước 1 và đăng nhập Microsoft trực tiếp.
3. Bước 1 – Tạo App Registration trên Azure (Microsoft Entra ID)
- Truy cập https://portal.azure.com → Microsoft Entra ID → App registrations → New registration.
- Đặt tên ứng dụng (ví dụ:
n8n-calendar-teams), mục Supported account types chọn loại phù hợp với tổ chức. - Mục Redirect URI: chọn Web và dán OAuth Redirect URL lấy từ n8n (xem Bước 2, mục 3) – thường có dạng
https://<tên-miền-n8n>/rest/oauth2-credential/callback. - Bấm Register, sau đó sao chép Application (client) ID.
- Vào Certificates & secrets → New client secret → sao chép ngay giá trị Value (chỉ hiển thị một lần).
- Vào API permissions → Add a permission → Microsoft Graph → Delegated permissions, thêm các quyền cần thiết, ví dụ:
- Cho Outlook Calendar:
offline_access,User.Read,Calendars.Read(hoặcCalendars.ReadWrite). - Cho Teams:
offline_access,User.Read,Chat.ReadWrite.
Sau đó bấm Grant admin consent nếu tổ chức yêu cầu quản trị viên phê duyệt.
- Cho Outlook Calendar:

Hình 2: Vào App registrations và bấm New registration

Hình 3: Điền thông tin đăng ký ứng dụng và Redirect URI
Sau khi bấm Register, tại trang Overview của ứng dụng, sao chép Application (client) ID; tiếp tục vào Certificates & secrets và API permissions như hướng dẫn ở trên.
⚠️ Bảo mật: Không chia sẻ Client Secret, Tenant ID, Client ID cho người khác hoặc đưa lên các nơi công khai.
4. Bước 2 – Kết nối Microsoft Outlook (Calendar) trong n8n
- Mở workflow M365 Calendar → Teams – Nhắc lịch họp đã import.
- Nhấp đúp vào node Microsoft Outlook Calendar.
- Tại ô Credential to connect with, chọn Create new credential. Sao chép OAuth Redirect URL hiển thị trong cửa sổ để dán vào Azure (Bước 1).
- Dán Client ID và Client Secret đã tạo ở Bước 1.
- Bấm Connect my account → đăng nhập tài khoản Microsoft 365 → Accept để cấp quyền.
- Khi thấy thông báo kết nối thành công (Account connected), bấm Save và đóng cửa sổ credential.
- Giữ nguyên các thiết lập khác của node: Resource = Event, Return All = bật, và bộ lọc thời gian trong Filters → Custom.

Hình 4: Node Microsoft Outlook Calendar – bấm Set up credential

Hình 5: Sao chép OAuth Redirect URL và dán Client ID

Hình 6: Dán Client Secret, bấm Save rồi Connect my account
5. Bước 3 – Kết nối Microsoft Teams trong n8n
- Nhấp đúp vào node Microsoft Teams – Gửi nhắc.
- Tại ô Credential to connect with → Create new credential.
- Nhập Client ID, Client Secret (có thể dùng chung App Registration ở Bước 1 nếu đã thêm đủ quyền cho Teams).
- Bấm Connect my account → đăng nhập Microsoft 365 → Accept → Save.
- Tại ô Chat (From list), chọn nhóm chat Teams sẽ nhận tin nhắn nhắc lịch. Nếu file JSON import có sẵn tên nhóm chat cũ, Quý khách cần chọn lại nhóm chat của mình.
- Kiểm tra Content Type = HTML và nội dung tin nhắn (Message) – có thể chỉnh sửa theo ý muốn.

Hình 7: Node Microsoft Teams – tạo credential, chọn nhóm chat, kiểm tra nội dung tin nhắn
6. Bước 4 – Chạy thử
- Tạo một cuộc họp thử trên Outlook Calendar, thời gian bắt đầu khoảng 10 phút sau thời điểm hiện tại.
- Trong n8n, bấm Execute workflow (Test workflow).
- Kiểm tra từng node chuyển sang màu xanh và nhóm chat Teams nhận được tin nhắn dạng:
⏰ ⏰ Nhắc lịch họp – còn 10 phút!
📌 Chủ đề: Họp thử
🕒 Bắt đầu: 10:30 – 29/10/2026
📍 Địa điểm: Online
Lưu ý: Do workflow ghi nhớ cuộc họp đã nhắc, nếu chạy thử lại cùng một cuộc họp sẽ không gửi lại tin nhắn. Hãy tạo cuộc họp thử mới hoặc đổi giờ cuộc họp để thử lại.

Hình 8: Execute workflow để chạy thử, Publish để kích hoạt
7. Bước 5 – Kích hoạt workflow
Sau khi chạy thử thành công, bấm nút Publish ở góc trên bên phải (mũi tên số 2 ở Hình 8; một số phiên bản cũ là công tắc Active) để workflow tự động chạy mỗi phút.
8. Tùy chỉnh thường dùng
- Đổi thời gian nhắc trước: trong node Kiểm tra còn 15 phút, sửa
const MAX = 15;. Nếu MAX lớn hơn 20, cần tăngplus({minutes: 20})trong Filters của node Outlook tương ứng. - Đổi tần suất kiểm tra: trong node Schedule Trigger (mặc định mỗi 1 phút).
- Đổi nội dung tin nhắn / múi giờ hiển thị: trong ô Message của node Teams (mặc định múi giờ
Asia/Ho_Chi_Minh). - Bổ sung tính năng: thêm link Teams Meeting, danh sách người tham dự, gửi qua email, v.v. tùy nhu cầu.
9. Mã JSON của workflow
Quý Khách có thể tham khảo đoạn mã JSON dưới đây. Quý Khách có thể tùy chỉnh hoặc bổ sung thêm các tính năng theo nhu cầu sử dụng.
Các giá trị dạng <YOUR_...> là thông tin riêng của từng tài khoản và sẽ được n8n tự điền khi Quý khách kết nối credential và chọn nhóm chat.
{
"name": "M365 Calendar → Teams - Nhắc lịch họp",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "minutes"
}
]
}
},
"id": "31f06f77-58fe-4d8c-8a92-e1b7c1b1539b",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
0,
0
]
},
{
"parameters": {
"resource": "event",
"returnAll": true,
"filters": {
"custom": "=start/dateTime ge '{{ $now.toUTC().toFormat(\"yyyy-MM-dd'T'HH:mm:ss\") }}' and start/dateTime le '{{ $now.toUTC().plus({minutes: 20}).toFormat(\"yyyy-MM-dd'T'HH:mm:ss\") }}'"
}
},
"id": "6e0d148e-f156-46f1-87ee-9e3d81992bee",
"name": "Microsoft Outlook Calendar",
"type": "n8n-nodes-base.microsoftOutlook",
"typeVersion": 2,
"position": [
224,
0
],
"webhookId": "<YOUR_WEBHOOK_ID>",
"credentials": {
"microsoftOutlookOAuth2Api": {
"id": "<YOUR_OUTLOOK_CREDENTIAL_ID>",
"name": "Microsoft Outlook account"
}
}
},
{
"parameters": {
"jsCode": "// Nhắc các cuộc họp sắp bắt đầu trong vòng MAX phút\n// Ghi nhớ cuộc họp đã nhắc → mỗi cuộc họp chỉ nhắc 1 lần\nconst MAX = 15;\n\nconst now = DateTime.now().toUTC();\nconst memory = $getWorkflowStaticData('global');\nmemory.reminded = memory.reminded || {};\n\n// Xóa bộ nhớ cũ hơn 1 ngày\nfor (const [key, ts] of Object.entries(memory.reminded)) {\n if (now.toMillis() - ts > 24 * 60 * 60 * 1000) delete memory.reminded[key];\n}\n\nconst results = [];\nfor (const item of $input.all()) {\n const ev = item.json;\n if (!ev.start || !ev.start.dateTime) continue;\n if (ev.isCancelled) continue;\n\n const raw = ev.start.dateTime.substring(0, 19); // bỏ phần .0000000\n const start = DateTime.fromISO(raw, { zone: ev.start.timeZone || 'UTC' });\n const minutesLeft = start.diff(now, 'minutes').minutes;\n\n if (minutesLeft > 0 && minutesLeft <= MAX) {\n const key = `${ev.id}|${raw}`;\n if (memory.reminded[key]) continue; // đã nhắc rồi → bỏ qua\n memory.reminded[key] = now.toMillis();\n results.push({ json: { ...ev, minutesLeft: Math.round(minutesLeft) } });\n }\n}\n\nreturn results;"
},
"id": "920f12cf-45fb-451f-a0a1-3ba31a8541fa",
"name": "Kiểm tra còn 15 phút",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
448,
0
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"leftValue": "={{ $json.subject }}",
"operator": {
"type": "string",
"operation": "notEmpty"
},
"id": "70eccd38-5313-467d-925a-80d015479bc9"
}
],
"combinator": "and"
},
"options": {}
},
"id": "44ceb2cc-1d7a-47c0-b39f-d57c658b4cee",
"name": "Có cuộc họp cần nhắc?",
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
672,
0
]
},
{
"parameters": {
"resource": "chatMessage",
"chatId": {
"__rl": true,
"value": "<YOUR_TEAMS_CHAT_ID>",
"mode": "list",
"cachedResultName": "<TEN_NHOM_CHAT>",
"cachedResultUrl": "<TEAMS_CHAT_URL>"
},
"contentType": "html",
"message": "=⏰ ⏰ <b>Nhắc lịch họp - còn {{ $json.minutesLeft }} phút!</b><br>\n📌 <b>Chủ đề:</b> {{ $json.subject }}<br>\n🕒 <b>Bắt đầu:</b> {{ DateTime.fromISO($json.start.dateTime, {zone: 'utc'}).setZone('Asia/Ho_Chi_Minh').toFormat('HH:mm - dd/MM/yyyy') }}<br>\n📍 <b>Địa điểm:</b> {{ $json.location?.displayName || 'Online' }}",
"options": {}
},
"id": "7bd1bde1-9674-4f70-bf69-509e339dc648",
"name": "Microsoft Teams - Gửi nhắc",
"type": "n8n-nodes-base.microsoftTeams",
"typeVersion": 2,
"position": [
928,
-128
],
"webhookId": "<YOUR_WEBHOOK_ID>",
"credentials": {
"microsoftTeamsOAuth2Api": {
"id": "<YOUR_TEAMS_CREDENTIAL_ID>",
"name": "Microsoft Teams account"
}
}
}
],
"pinData": {},
"connections": {
"Schedule Trigger": {
"main": [
[
{
"node": "Microsoft Outlook Calendar",
"type": "main",
"index": 0
}
]
]
},
"Microsoft Outlook Calendar": {
"main": [
[
{
"node": "Kiểm tra còn 15 phút",
"type": "main",
"index": 0
}
]
]
},
"Kiểm tra còn 15 phút": {
"main": [
[
{
"node": "Có cuộc họp cần nhắc?",
"type": "main",
"index": 0
}
]
]
},
"Có cuộc họp cần nhắc?": {
"main": [
[
{
"node": "Microsoft Teams - Gửi nhắc",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {
"executionOrder": "v1",
"binaryMode": "separate",
"availableInMCP": false,
"timeSavedMode": "fixed",
"timezone": "Asia/Ho_Chi_Minh",
"callerPolicy": "workflowsFromSameOwner"
},
"versionId": "<YOUR_VERSION_ID>",
"meta": {
"templateCredsSetupCompleted": true,
"instanceId": "<YOUR_INSTANCE_ID>"
},
"nodeGroups": [],
"id": "<YOUR_WORKFLOW_ID>",
"tags": []
}
10. Một số lỗi thường gặp
- Không nhận được tin nhắn: kiểm tra workflow đã Active, tài khoản kết nối có quyền truy cập lịch và là thành viên nhóm chat Teams.
- Lỗi quyền (403 / Insufficient privileges): kiểm tra lại API permissions trên Azure và Grant admin consent.
- Lỗi redirect_uri mismatch: Redirect URI trên Azure phải trùng khớp với OAuth Redirect URL trong n8n.
- Giờ hiển thị sai: kiểm tra múi giờ trong Settings của workflow và trong nội dung Message.
📢 Lưu ý: Bài viết mang tính chất tham khảo. Quý khách có thể tự điều chỉnh hoặc bổ sung thêm các tính năng khác theo nhu cầu sử dụng của mình.















