8
n8n 中文网amn8n.com

每日生日庆祝(代码节点最终版本)

高级

这是一个Personal Productivity, Multimodal AI领域的自动化工作流,包含 17 个节点。主要使用 If, Code, Gmail, Slack, HttpRequest 等节点。 基于NASA图片、GPT-4、Gmail和Slack的自动化太空主题生日邮件

前置要求
  • Google 账号和 Gmail API 凭证
  • Slack Bot Token 或 Webhook URL
  • 可能需要目标 API 的认证凭证
  • Google Sheets API 凭证
  • OpenAI API Key
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "0czfWskRwpjMRqaZ",
  "meta": {
    "instanceId": "66e13aec947801e3f08d27a590fb0e07109805e23a7eabde7c0647150db10195",
    "templateCredsSetupCompleted": true
  },
  "name": "每日生日庆祝(代码节点最终版本)",
  "tags": [],
  "nodes": [
    {
      "id": "adaf007f-0c2d-4dc2-a8f9-55b00f7f3d53",
      "name": "每天早上 7:00",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        256,
        -208
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 7 * * *"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "721377a2-196c-4d2e-8c33-33ffa5f9c765",
      "name": "获取生日名单",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        480,
        -208
      ],
      "parameters": {
        "sheetName": "",
        "documentId": ""
      },
      "typeVersion": 4.7
    },
    {
      "id": "18bd2530-8a96-4b66-8792-2f6ab0449e17",
      "name": "过滤今日生日",
      "type": "n8n-nodes-base.code",
      "position": [
        704,
        -208
      ],
      "parameters": {
        "jsCode": "const today = new Date();\nconst todayMonth = today.getMonth() + 1; // 1-12\nconst todayDay = today.getDate();\n\nconst birthdaysToday = [];\n\nfor (const item of $input.all()) {\n  const birthdayStr = item.json.birthday || item.json.Birthday;\n  if (!birthdayStr) continue;\n  \n  const birthday = new Date(birthdayStr);\n  const birthMonth = birthday.getMonth() + 1;\n  const birthDay = birthday.getDate();\n  \n  if (birthMonth === todayMonth && birthDay === todayDay) {\n    birthdaysToday.push(item.json);\n  }\n}\n\nif (birthdaysToday.length > 0) {\n  // Pass along the list of people with birthdays today\n  return [{ json: { birthdays: birthdaysToday } }];\n}\n\n// If no birthdays, return empty to stop the workflow here\nreturn [];"
      },
      "typeVersion": 2
    },
    {
      "id": "66f0cde9-e2c6-4a02-81bc-c5c8cea8048b",
      "name": "今日有生日吗?",
      "type": "n8n-nodes-base.if",
      "position": [
        928,
        -208
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "1fd71fc8-79c7-432f-88b4-a1418f6bed90",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $input.all().length }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "707d5452-5d02-4372-aaa1-e4ffc609a9b9",
      "name": "准备生日数据",
      "type": "n8n-nodes-base.code",
      "position": [
        1376,
        -304
      ],
      "parameters": {
        "jsCode": "const epicImages = $('Fetch NASA EPIC Images2').all().map(item => item.json);\nconst allBirthdays = $('Filter Today\\'s Birthdays').first().json.birthdays;\n\n// We only need one image, let's take the first one returned by the API\nconst latestImage = epicImages[0];\n\nconst results = [];\n\n// Construct the full image URL from the EPIC data parts\nconst d = new Date(latestImage.date);\nconst year = d.getFullYear();\nconst month = ('0' + (d.getMonth() + 1)).slice(-2);\nconst day = ('0' + d.getDate()).slice(-2);\nconst imageName = latestImage.image;\nconst imageUrl = `https://epic.gsfc.nasa.gov/archive/natural/${year}/${month}/${day}/png/${imageName}.png`;\n\n// Combine the image data with each birthday person's data\nfor (const person of allBirthdays) {\n  results.push({\n    json: {\n      ...person, // This includes name, email, birthday\n      epicCaption: latestImage.caption,\n      epicDate: latestImage.date,\n      epicImageUrl: imageUrl\n    }\n  });\n}\n\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "ec074153-a990-4f9a-891a-6e0e3d3096f9",
      "name": "生成太空生日消息",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1600,
        -304
      ],
      "parameters": {
        "text": "=Person's name: {{ $json.name || $json.Name }}\nToday's Earth photo caption: {{ $json.epicCaption }}",
        "options": {
          "systemMessage": "You are a creative birthday message writer specializing in space-themed greetings.\n\nYour task is to:\n1. Generate a fun, space-themed birthday message for the person, mentioning our home planet Earth.\n2. Incorporate the NASA EPIC photo's caption into the message.\n3. Keep the message to approximately 120 characters.\n4. Make it celebratory and cosmic!\n5. Return ONLY the birthday message text, nothing else."
        },
        "promptType": "define"
      },
      "typeVersion": 3
    },
    {
      "id": "3cf8af5f-0019-46d2-8d7b-310a31b6fcaf",
      "name": "OpenAI 聊天模型",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1680,
        -80
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini",
          "cachedResultName": "gpt-4.1-mini"
        },
        "options": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "0550ac86-0258-4819-a2e5-a0cf737003bd",
      "name": "统计生日数量",
      "type": "n8n-nodes-base.code",
      "position": [
        1152,
        -112
      ],
      "parameters": {
        "jsCode": "const birthdays = $input.item.json.birthdays || [];\nconst count = birthdays.length;\nreturn [{ json: { birthdayCount: count } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "0a531f86-adb7-4518-8aee-3e6e9d72e907",
      "name": "发布 Slack 通知",
      "type": "n8n-nodes-base.slack",
      "position": [
        1376,
        -112
      ],
      "webhookId": "16e4d5a6-43dd-4694-9509-50f05c4db2f3",
      "parameters": {
        "text": "=🎂 Birthdays today: {{ $json.birthdayCount }}",
        "select": "channel",
        "channelId": "",
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.3
    },
    {
      "id": "2fd5a4d7-0181-42e1-936c-b59046c714df",
      "name": "获取 NASA EPIC 图像2",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1152,
        -304
      ],
      "parameters": {
        "url": "https://epic.gsfc.nasa.gov/api/natural",
        "options": {
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "2496302d-6108-43cb-b6b6-2eedbad73af5",
      "name": "发送生日邮件",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2400,
        -304
      ],
      "webhookId": "58c2dcc8-58f5-4dd6-a291-066ff0f05a72",
      "parameters": {
        "sendTo": "=={{ $json.Email }}",
        "message": "=<h2>Happy Birthday {{ $json.name || $json.Name }}! 🎂🌏</h2>\n\n<p>{{ $json.birthdayMessage }}</p>\n\n<h3>A View of Our Home Planet For You:</h3>\n<p><strong>{{ $json.epicCaption }}</strong></p>\n<img src=\"{{ $json.epicImageUrl }}\" alt=\"NASA EPIC Earth Photo\" style=\"max-width: 600px; height: auto;\" />\n\n<p>This photo of Earth was taken on {{ new Date($json.epicDate).toLocaleDateString() }}.</p>\n\n<p>Wishing you a wonderful year ahead! 🌟</p>",
        "options": {},
        "subject": "=🎂🌏 Happy Birthday {{ $json.Name }} !"
      },
      "typeVersion": 2.1
    },
    {
      "id": "b541cac2-92d9-45ca-b75c-b2a783c2a380",
      "name": "为 Gmail 格式化",
      "type": "n8n-nodes-base.code",
      "position": [
        2032,
        -304
      ],
      "parameters": {
        "jsCode": "// --- ここから下をすべてコピーする ---\n\n// 個人情報が入った荷物を、すべて持ってくる\nconst personalInfoItems = $('Prepare Birthday Data').all();\n\n// AI賢者からのメッセージが入った荷物を、すべて持ってくる\nconst birthdayMessageItems = $('Generate Space Birthday Message').all();\n\n// 荷物の数が合っているか、念のために確認する\nif (personalInfoItems.length !== birthdayMessageItems.length) {\n  throw new Error(`荷物の数が合いません!個人情報は${personalInfoItems.length}件、AIメッセージは${birthdayMessageItems.length}件です。これではペアを作れません!`);\n}\n\n// 完成したプレゼントを入れるための、空の箱を用意する\nconst finalPackages = [];\n\n// forループという魔法の呪文で、荷物を先頭から一つずつ処理していく\nfor (let i = 0; i < personalInfoItems.length; i++) {\n  const personalInfo = personalInfoItems[i].json;\n  const birthdayMessage = birthdayMessageItems[i].json.output;\n\n  // 2つの情報を合体させて、一つのきれいな包みにする\n  finalPackages.push({\n    json: {\n      ...personalInfo,\n      birthdayMessage: birthdayMessage,\n    }\n  });\n}\n\n// 完成したプレゼントを、すべて次の工程へ渡す\nreturn finalPackages;\n\n// --- ここまでをすべてコピーする ---"
      },
      "typeVersion": 2
    },
    {
      "id": "a4b3d302-e082-4fcd-9caf-f241422a913c",
      "name": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2240,
        -544
      ],
      "parameters": {
        "color": "#FFFFFF",
        "width": 300,
        "height": 208,
        "content": "## 4. 配置电子邮件发件人"
      },
      "typeVersion": 1
    },
    {
      "id": "03d1abb0-c969-40d1-8f6e-af82984f37f9",
      "name": "便签1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        -736
      ],
      "parameters": {
        "height": 1296,
        "content": "## 通过 Gmail 和 Slack 发送每日太空主题生日祝福"
      },
      "typeVersion": 1
    },
    {
      "id": "8710f379-ac18-43e2-8115-696d22e6a832",
      "name": "便签2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        416,
        -576
      ],
      "parameters": {
        "height": 336,
        "content": "## 1. 配置生日名单"
      },
      "typeVersion": 1
    },
    {
      "id": "675f8a58-0e45-47d0-bcf3-764ec00ca94b",
      "name": "便签4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1584,
        -576
      ],
      "parameters": {
        "height": 224,
        "content": "## 2. 配置 OpenAI 模型"
      },
      "typeVersion": 1
    },
    {
      "id": "31428758-c1cd-4cff-8bb7-cd6dbdc861d8",
      "name": "便签3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1248,
        48
      ],
      "parameters": {
        "height": 240,
        "content": "## 3. 配置 Slack 通知"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {
    "Generate Space Birthday Message": [
      {
        "json": {
          "output": "Happy Birthday, 星野 光! Celebrate your day from Earth, seen by NASA's EPIC—our cosmic home in the vast universe! 🎉🌍✨"
        }
      },
      {
        "json": {
          "output": "Happy Birthday 弟子 二号! From Earth to the stars, NASA's EPIC sees your cosmic shine bright today! 🚀🌍🎉"
        }
      }
    ]
  },
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "75159693-40d3-49a5-986e-f6878b2a5b5d",
  "connections": {
    "Count Birthdays": {
      "main": [
        [
          {
            "node": "Post Slack Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format for Gmail": {
      "main": [
        [
          {
            "node": "Send Birthday Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Generate Space Birthday Message",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Get Birthday Roster": {
      "main": [
        [
          {
            "node": "Filter Today's Birthdays",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Any Birthdays Today?": {
      "main": [
        [
          {
            "node": "Fetch NASA EPIC Images2",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Count Birthdays",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Every Morning at 7:00": {
      "main": [
        [
          {
            "node": "Get Birthday Roster",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Birthday Data": {
      "main": [
        [
          {
            "node": "Generate Space Birthday Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch NASA EPIC Images2": {
      "main": [
        [
          {
            "node": "Prepare Birthday Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Today's Birthdays": {
      "main": [
        [
          {
            "node": "Any Birthdays Today?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Space Birthday Message": {
      "main": [
        [
          {
            "node": "Format for Gmail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

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

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

高级 - 个人效率, 多模态 AI

需要付费吗?

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

工作流信息
难度等级
高级
节点数量17
分类2
节点类型10
难度说明

适合高级用户,包含 16+ 个节点的复杂工作流

外部链接
在 n8n.io 查看

分享此工作流