8
n8n 中文网amn8n.com

将 Google 日历的每周会议安排预览发送到 Gmail

初级

这是一个Personal Productivity领域的自动化工作流,包含 5 个节点。主要使用 Cron, Gmail, Function, GoogleCalendar 等节点。 将 Google 日历的每周会议安排预览发送到 Gmail

前置要求
  • Google 账号和 Gmail API 凭证
工作流预览
可视化展示节点连接关系,支持缩放和平移

无法加载工作流预览

导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "nodes": [
    {
      "name": "周日晚上触发器",
      "type": "n8n-nodes-base.cron",
      "notes": {
        "text": "### 1. Trigger on Sunday Evening\n\nThis `Cron` node is configured to run automatically every **Sunday at 7:00 PM (19:00)** your server's local time.\n\n**To change the schedule:**\n* Adjust 'Time' to your preferred hour.\n* Adjust 'Weekdays' if you want it to run on a different day.",
        "position": "right"
      },
      "position": [
        240,
        300
      ],
      "parameters": {
        "mode": "everyWeek",
        "value": {
          "time": "19:00",
          "weekdays": [
            "sunday"
          ]
        },
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "name": "计算周日期",
      "type": "n8n-nodes-base.function",
      "notes": {
        "text": "### 2. Calculate Upcoming Week Dates\n\nThis `Function` node uses JavaScript (with Luxon's DateTime library, which n8n uses internally) to calculate the start and end dates for the *upcoming* week (Monday to Sunday).\n\n**Output:** It generates two fields:\n* `startDate`: The ISO string for next Monday (00:00:00).\n* `endDate`: The ISO string for next Sunday (23:59:59).\n\n**No configuration needed here**, it's ready to go.",
        "position": "right"
      },
      "position": [
        480,
        300
      ],
      "parameters": {
        "options": {},
        "function": "const DateTime = this.getNodeParameter('DateTime');\n\nconst now = DateTime.now();\n\n// Calculate next Monday (start of upcoming week)\nconst nextMonday = now.startOf('week').plus({ weeks: 1 });\n\n// Calculate next Sunday (end of upcoming week)\nconst nextSunday = nextMonday.plus({ days: 6 }).endOf('day');\n\nreturn [{ json: { \n  startDate: nextMonday.toISO(), \n  endDate: nextSunday.toISO() \n} }];"
      },
      "typeVersion": 1
    },
    {
      "name": "获取日历事件",
      "type": "n8n-nodes-base.googleCalendar",
      "notes": {
        "text": "### 3. Get Upcoming Calendar Events\n\nThis `Google Calendar` node fetches all events within the calculated `startDate` and `endDate` range.\n\n**Setup:**\n1.  **Google Calendar Credential:** Click on 'Credentials' and select 'New Credential'. Choose 'Google Calendar OAuth2 API'. Follow the n8n instructions to connect your Google account. (You might need to enable the Google Calendar API in your Google Cloud Project).\n2.  **Calendar ID:** `primary` usually works for your main calendar. If you want to use a specific calendar, get its ID from Google Calendar settings and paste it here.\n3.  **Time Min/Max:** These are automatically populated with the `startDate` and `endDate` from the previous 'Calculate Week Dates' node.",
        "position": "right"
      },
      "position": [
        720,
        300
      ],
      "parameters": {
        "options": {
          "orderBy": "startTime",
          "maxResults": 20,
          "singleEvents": true
        },
        "timeMax": "={{ $json.endDate }}",
        "timeMin": "={{ $json.startDate }}",
        "operation": "getAll",
        "calendarId": "=primary"
      },
      "credentials": {
        "googleCalendarOAuth2Api": {
          "id": "YOUR_GOOGLE_CALENDAR_CREDENTIAL_ID",
          "resolve": false
        }
      },
      "typeVersion": 2
    },
    {
      "name": "格式化会议摘要",
      "type": "n8n-nodes-base.function",
      "notes": {
        "text": "### 4. Format Meeting Summary\n\nThis `Function` node processes the calendar events and formats them into a readable summary string for your email.\n\n**Key features:**\n* Handles cases with no events.\n* Groups events by day.\n* Sorts events chronologically within each day.\n* Includes time, title, and location (if available).\n* Uses basic Markdown for formatting (e.g., `**Day Name**`).\n\n**No configuration needed here**, it's pre-programmed to format your events.",
        "position": "right"
      },
      "position": [
        960,
        300
      ],
      "parameters": {
        "options": {},
        "function": "let summary = \"\";\n\nif (items.length === 0) {\n  summary = \"Good news! You have no meetings scheduled for the upcoming week.\\n\";\n} else {\n  summary = \"Here's a summary of your upcoming meetings for the week:\\n\\n\";\n\n  // Group events by day\n  const eventsByDay = {};\n  for (const item of items) {\n    const event = item.json;\n    const startDateTime = new Date(event.start.dateTime || event.start.date); // Handle all-day events\n    const dateKey = startDateTime.toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric' });\n\n    if (!eventsByDay[dateKey]) {\n      eventsByDay[dateKey] = [];\n    }\n    eventsByDay[dateKey].push(event);\n  }\n\n  // Sort days chronologically\n  const sortedDays = Object.keys(eventsByDay).sort((a, b) => {\n    const dateA = new Date(a);\n    const dateB = new Date(b);\n    return dateA - dateB;\n  });\n\n  // Build the summary string\n  for (const day of sortedDays) {\n    summary += `**${day}**:\\n`;\n    // Sort events within the day by time\n    eventsByDay[day].sort((a, b) => {\n      const timeA = new Date(a.start.dateTime || a.start.date);\n      const timeB = new Date(b.start.dateTime || b.start.date);\n      return timeA - timeB;\n    });\n    for (const event of eventsByDay[day]) {\n      const startTime = event.start.dateTime ? new Date(event.start.dateTime).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: true }) : 'All Day';\n      const endTime = event.end.dateTime ? new Date(event.end.dateTime).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: true }) : '';\n      const location = event.location ? ` (at ${event.location})` : '';\n      const summaryText = event.summary || 'No Title';\n\n      if (startTime === 'All Day') {\n        summary += `- ${summaryText} (All Day)${location}\\n`;\n      } else {\n        summary += `- ${startTime}${endTime ? ` - ${endTime}` : ''}: ${summaryText}${location}\\n`;\n      }\n    }\n    summary += \"\\n\"; // Add a blank line between days\n  }\n}\n\nreturn [{ json: { summaryEmailContent: summary } }];"
      },
      "typeVersion": 1
    },
    {
      "name": "发送摘要邮件",
      "type": "n8n-nodes-base.gmail",
      "notes": {
        "text": "### 5. Send Summary Email\n\nThis `Gmail` node sends the compiled meeting summary to your inbox.\n\n**Setup:**\n1.  **Gmail Credential:** Click 'Credentials' and select 'New Credential'. Choose 'Gmail API'. Follow the n8n instructions to connect your Gmail account.\n2.  **From Email:** Enter your Gmail address (this must be the same account you authenticated).\n3.  **To Email:** **IMPORTANT: Change `YOUR_RECIPIENT_EMAIL@example.com` to your actual email address!**\n4.  **Subject:** Automatically includes the upcoming week's date range.\n5.  **Text:** Uses the `summaryEmailContent` generated by the previous node.\n\nAfter setting up, click 'Execute Workflow' (from the 'Sunday Evening Trigger' node) to test sending an email!",
        "position": "right"
      },
      "position": [
        1200,
        300
      ],
      "parameters": {
        "text": "Hello!\n\n{{ $json.summaryEmailContent }}\n\nHave a productive week!\n\nBest,\nYour n8n Automation",
        "options": {},
        "subject": "Your Upcoming Meeting Schedule: {{ DateTime.now().plus({ weeks: 1 }).startOf('week').toFormat('LLL dd') }} - {{ DateTime.now().plus({ weeks: 1 }).endOf('week').toFormat('LLL dd') }}",
        "toEmail": "YOUR_RECIPIENT_EMAIL@example.com",
        "fromEmail": "YOUR_GMAIL_EMAIL@gmail.com"
      },
      "credentials": {
        "gmailApi": {
          "id": "YOUR_GMAIL_CREDENTIAL_ID",
          "resolve": false
        }
      },
      "typeVersion": 2
    }
  ],
  "pinData": {},
  "version": 1,
  "connections": {
    "Get Calendar Events": {
      "main": [
        [
          {
            "node": "Format Meeting Summary",
            "type": "main"
          }
        ]
      ]
    },
    "Calculate Week Dates": {
      "main": [
        [
          {
            "node": "Get Calendar Events",
            "type": "main"
          }
        ]
      ]
    },
    "Format Meeting Summary": {
      "main": [
        [
          {
            "node": "Send Summary Email",
            "type": "main"
          }
        ]
      ]
    },
    "Sunday Evening Trigger": {
      "main": [
        [
          {
            "node": "Calculate Week Dates",
            "type": "main"
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

初级 - 个人效率

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
初级
节点数量5
分类1
节点类型4
难度说明

适合 n8n 新手,包含 1-5 个节点的简单工作流

作者
Piotr Sobolewski

Piotr Sobolewski

@piotrsobolewski

AI PhD with 7 years experience as a game dev CEO, currently teaching, helping others and building something new.

外部链接
在 n8n.io 查看

分享此工作流