AutomationFlowsAI & RAG › Google Sheets to Gmail Newsletter with AI

Google Sheets to Gmail Newsletter with AI

Original n8n title: Automate Newsletter Creation & Client Delivery with Gpt-4o, Google Sheets

ByAmit Mehta @amitswba on n8n.io

This workflow automates the complete newsletter management process from content creation to client delivery, using Google Sheets, AI content generation, Google Drive, and Gmail.

Event trigger★★★★☆ complexityAI-powered15 nodesGoogle SheetsOpenAIGoogle DriveGmail
AI & RAG Trigger: Event Nodes: 15 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #5694 — we link there as the canonical source.

This workflow follows the Gmail → Google Drive recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "TEMPLATE_WORKFLOW_ID",
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "name": "Newsletter",
  "tags": [],
  "nodes": [
    {
      "id": "88924d6c-0524-45c6-8982-b43bc79951c6",
      "name": "When clicking 'Test workflow'",
      "type": "n8n-nodes-base.manualTrigger",
      "notes": "\ud83d\ude80 START HERE: Click to generate newsletters from pending topics in your Google Sheet",
      "position": [
        -40,
        -180
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "d386375c-ecac-4335-a29a-cd39d9233f07",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "notes": "\u23f0 AUTOMATED: Runs daily to send approved newsletters to clients. Configure timing in settings.",
      "position": [
        -40,
        230
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "ca49af2b-0d7f-4aa1-b63c-dc828bfeb7d6",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "notes": "\ud83d\udd04 BATCH PROCESSING: Handles multiple client emails efficiently. Prevents rate limiting and ensures reliable delivery.",
      "position": [
        840,
        230
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "2208eb0e-a0aa-4082-905b-166fa521b75a",
      "name": "Get topic from newsletter sheet",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "\ud83d\udcca FETCH TOPICS: Gets all pending newsletter topics from your Google Sheet. Only processes items with 'Pending' status.",
      "position": [
        180,
        -180
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "Pending",
              "lookupColumn": "Status"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit#gid=0",
          "cachedResultName": "Topic"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID_HERE",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit?usp=drivesdk",
          "cachedResultName": "Newsletter"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5,
      "alwaysOutputData": true
    },
    {
      "id": "2b47d026-a70e-40d5-a2c4-4f07551f0eef",
      "name": "Validate Status as Pending",
      "type": "n8n-nodes-base.if",
      "notes": "\u2705 DATE FILTER: Only processes newsletters scheduled for today. Prevents processing old or future-dated items.",
      "position": [
        400,
        -180
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "2d883784-6213-45b4-944f-55c0ffcc19b6",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.Date }}",
              "rightValue": "={{ new Date().toLocaleDateString('en-US') }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "448be138-181b-4bda-95dd-66d632635256",
      "name": "Create HTML for Newsletter",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "notes": "\ud83e\udd16 AI MAGIC: Uses GPT-4O to create professional HTML newsletter content. Customize the prompt here for different styles and tones.",
      "position": [
        620,
        -180
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o",
          "cachedResultName": "GPT-4O"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=Create an HTML newsletter on the topic:{{ $json.Topic }}. \n Include these hook sentences:{{ $json.hooks }} . \n Structure with a header, body paragraphs, and footer\n"
            }
          ]
        }
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "f552d84a-9d14-4cb1-89d7-d99bc9784a5e",
      "name": "Prepare Data to create word doc",
      "type": "n8n-nodes-base.code",
      "notes": "\ud83d\udd27 FORMAT PREP: Converts AI-generated HTML into proper file format for Google Drive upload. Auto-generates timestamped filename.",
      "position": [
        996,
        -180
      ],
      "parameters": {
        "jsCode": "// Get HTML content from current input\nconst htmlContent = $input.first().json.message.content;\n\n// Generate filename with current date\nconst currentDate = new Date().toISOString().split('T')[0];\nconst filename = `document_${currentDate}.html`;\n\n// Convert string to binary buffer\nconst buffer = Buffer.from(htmlContent, 'utf8');\n\nreturn [{\n  json: {\n    fileName: filename,\n    mimeType: 'text/html'\n  },\n  binary: {\n    data: buffer\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "f2421bc4-2045-46c9-beab-ff5459b4a17c",
      "name": "Upload doc to google drive",
      "type": "n8n-nodes-base.googleDrive",
      "notes": "\ud83d\udcbe CLOUD STORAGE: Saves the newsletter to your Google Drive 'Newsletter' folder. Creates shareable link for easy access.",
      "position": [
        1216,
        -180
      ],
      "parameters": {
        "name": "=newsletter-{{ $('Get topic from newsletter sheet').item.json.Date }}.html",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive",
          "cachedResultUrl": "https://drive.google.com/drive/my-drive",
          "cachedResultName": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_DRIVE_FOLDER_ID",
          "cachedResultUrl": "https://drive.google.com/drive/folders/YOUR_GOOGLE_DRIVE_FOLDER_ID",
          "cachedResultName": "Newsletter"
        },
        "inputDataFieldName": "=data"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "6b39c176-25cf-4b47-a25c-8b886f0709ba",
      "name": "Send an email to admin",
      "type": "n8n-nodes-base.gmail",
      "notes": "\ud83d\udce7 ADMIN ALERT: Notifies you when newsletter is ready for review. Update email address to yours. Includes Google Drive link.",
      "position": [
        1436,
        -180
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "=Review the attached newsletter  {{ $json.webViewLink }}",
        "options": {},
        "subject": "=Newsletter Preview for {{ $('Get topic from newsletter sheet').item.json.Date }} and HTML body attached",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "8e7c42de-3fd8-4acc-afdb-83491674bf7b",
      "name": "Update Status as Generated",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "\ud83d\udcdd TRACKING UPDATE: Marks newsletter as 'Generated' in Google Sheet. Adds timestamp and document URL for audit trail.",
      "position": [
        1656,
        -180
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ $('Get topic from newsletter sheet').item.json.Date }}",
            "Status": "Generated",
            "Timestamp": "={{ $('Upload doc to google drive').item.json.createdTime }}",
            "Document URL": "={{ $('Upload doc to google drive').item.json.webViewLink }}"
          },
          "schema": [
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Topic",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Topic",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "hooks",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "hooks",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Document URL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Document URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Date"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit#gid=0",
          "cachedResultName": "Topic"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID_HERE",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit?usp=drivesdk",
          "cachedResultName": "Newsletter"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "0f6f5d15-dbd9-415b-923d-81809708542d",
      "name": "Validate Status as Approved",
      "type": "n8n-nodes-base.if",
      "notes": "\u2705 APPROVAL CHECK: Only sends newsletters with 'Approved' status. Prevents accidental sending of unreviewed content.",
      "position": [
        400,
        230
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "b3730359-d11f-4a9c-aa5f-f4dcc1f0702e",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.Status }}",
              "rightValue": "Approved"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "f03eed28-1c06-401e-8c4b-ba5b5891b048",
      "name": "Pick records to send email to client",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "\ud83d\udcec CLIENT QUEUE: Fetches all newsletter records ready for client delivery. Runs on schedule to automate sending.",
      "position": [
        180,
        230
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit#gid=0",
          "cachedResultName": "Topic"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID_HERE",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit?usp=drivesdk",
          "cachedResultName": "Newsletter"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "23ae0b93-f121-493b-a0d1-80fc748137a2",
      "name": "Get Client email address",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "\ud83d\udc65 CLIENT LOOKUP: Gets email addresses from the 'Email' sheet. Maintains separate client database for easy management.",
      "position": [
        620,
        230
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_EMAIL_SHEET_GID",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit#gid=YOUR_EMAIL_SHEET_GID",
          "cachedResultName": "Email"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID_HERE",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit?usp=drivesdk",
          "cachedResultName": "Newsletter"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "4281a45c-5af5-4311-bca6-aaee14152afc",
      "name": "Send email to client",
      "type": "n8n-nodes-base.gmail",
      "notes": "\ud83d\udce4 CLIENT DELIVERY: Sends newsletter to individual clients via Gmail. Customize subject line and message template here.",
      "position": [
        1060,
        280
      ],
      "parameters": {
        "sendTo": "={{ $json.Email }}",
        "message": "=Attached is the newsletter  {{ $('Pick records to send email to client').item.json['Document URL'] }}",
        "options": {},
        "subject": "Newsletter",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "c2634a85-88f6-49b5-bd14-6e03336a49f2",
      "name": "Update status as Sent",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "\u2705 COMPLETION TRACKING: Marks newsletter as 'Sent' to prevent duplicate deliveries. Maintains complete audit trail.",
      "position": [
        1060,
        80
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ $('Pick records to send email to client').item.json.Date }}",
            "Status": "Sent"
          },
          "schema": [
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Topic",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Topic",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "hooks",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "hooks",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Timestamp",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Document URL",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Document URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Date"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit#gid=0",
          "cachedResultName": "Topic"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID_HERE",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit?usp=drivesdk",
          "cachedResultName": "Newsletter"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "TEMPLATE_VERSION_ID",
  "connections": {
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "Update status as Sent",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send email to client",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Pick records to send email to client",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send email to client": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send an email to admin": {
      "main": [
        [
          {
            "node": "Update Status as Generated",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Client email address": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create HTML for Newsletter": {
      "main": [
        [
          {
            "node": "Prepare Data to create word doc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload doc to google drive": {
      "main": [
        [
          {
            "node": "Send an email to admin",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Status as Pending": {
      "main": [
        [
          {
            "node": "Create HTML for Newsletter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Status as Approved": {
      "main": [
        [
          {
            "node": "Get Client email address",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking 'Test workflow'": {
      "main": [
        [
          {
            "node": "Get topic from newsletter sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get topic from newsletter sheet": {
      "main": [
        [
          {
            "node": "Validate Status as Pending",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Data to create word doc": {
      "main": [
        [
          {
            "node": "Upload doc to google drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pick records to send email to client": {
      "main": [
        [
          {
            "node": "Validate Status as Approved",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow automates the complete newsletter management process from content creation to client delivery, using Google Sheets, AI content generation, Google Drive, and Gmail.

Source: https://n8n.io/workflows/5694/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

An n8n-based automation that generates client proposals from a form, lets you review everything in one place, and sends the proposal only when you approve it.

Form Trigger, Google Sheets Trigger, OpenAI +4
AI & RAG

Overview

Gmail Trigger, Google Drive, OpenAI +4
AI & RAG

💥 Automate YouTube thumbnail creation from video links -vide. Uses telegramTrigger, httpRequest, googleDrive, gmail. Event-driven trigger; 25 nodes.

Telegram Trigger, HTTP Request, Google Drive +6
AI & RAG

💥 Automate YouTube thumbnail creation from video links -vide. Uses telegramTrigger, httpRequest, googleDrive, gmail. Event-driven trigger; 25 nodes.

Telegram Trigger, HTTP Request, Google Drive +6
AI & RAG

💥 Automate YouTube thumbnail creation from video links -vide. Uses telegramTrigger, httpRequest, googleDrive, gmail. Event-driven trigger; 25 nodes.

Telegram Trigger, HTTP Request, Google Drive +6