0

This is the code I used (found online, not my own), but I can't figure out how to add an attachment to this code.

function sendEmails() {
  // Load the spreadsheet data
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const allData = sheet.getDataRange().getValues();
  const headers = allData[0];
  const rows = allData.slice(1);

  // Helper function to detect column indices
  const getColIndex = (headerName) => {
    const index = headers.indexOf(headerName);
    if (index === -1) throw new Error(`Header "${headerName}" not found.`);
    return index;
  };

  // Detect column indices
  const nameCol = getColIndex("Name");
  const emailCol = getColIndex("Email");
  const sentCol = getColIndex("Sent");

  // Loop through the entire spreadsheet
  rows.forEach((row, i) => {
    const name = row[nameCol];
    const email = row[emailCol];
    const sent = row[sentCol];

    // Skip rows that have been sent already
    if (!email || sent) return;

    // Send an email with a personalized subject and body
    MailApp.sendEmail(
      email,
      `Submission received`,
      `Dear ${name},\n\nThank you for your submission. We'll be in touch shortly.\n\nYours truly,\nJames`
    );

    // Log timestamp in the Sent column
    sheet.getRange(i + 2, sentCol + 1).setValue(new Date());
  });
}

I have changed the headers "email" and "name" to match the headers of my google sheet. And it worked.

The attachment is in my google drive and this is my latest try to add an attachment, this time not even an email got sent.

function sendEmails() {
  // Load the spreadsheet data
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const allData = sheet.getDataRange().getValues();
  const headers = allData[0];
  const rows = allData.slice(1);

  // Helper function to detect column indices
  const getColIndex = (headerName) => {
    const index = headers.indexOf(headerName);
    if (index === -1) throw new Error(`Header "${headerName}" not found.`);
    return index;
  };

  // Detect column indices
  const nameCol = getColIndex("Namn");
  const emailCol = getColIndex("E-postadress");
  const sentCol = getColIndex("Sent");

  // Loop through the entire spreadsheet
  rows.forEach((row, i) => {
    const name = row[nameCol];
    const email = row[emailCol];
    const sent = row[sentCol];

    // Skip rows that have been sent already
    if (!email || sent) return;

    // Send an email with a personalized subject and body
    function sendEmails(){
      const id = '1ezM-QiJ73Ry4xmNMdWHdC-4jXJ4gUHhB';
      const sub = `Postpartum Checklist`
      const body = `Dear ${name},\n\nSå härligt att du tar dina första steg mot en positiv postpartum upplevelse. Oavsett om det är din första eller fjärde gång, hoppas jag att du hittar lite trygghet i den här checklistan.\n\nLadda ner och skriv ut den, eller få ditt utskriven exemplar från mig om du valde att bli kontaktad för en första konsultation.\n\nMvh,\nLeila`
      const att = DriveApp.getFileById(id);
      MailApp.sendEmail(email,sub, body, att);
    }

    // Log timestamp in the Sent column
    sheet.getRange(i + 2, sentCol + 1).setValue(new Date());
  });
}
2
  • 3
    You can not pass a file directly as 4th parameter. developers.google.com/apps-script/reference/mail/… has an example that sends two attachments, one even fetched from Google Drive, so pretty much exactly what you want, no? Commented Aug 27 at 13:47
  • See these related SO posts for additional insights. This might solve your problem. Commented Aug 27 at 19:26

1 Answer 1

-1
  • You must pass options object to MailApp.sendEmail to include attachments.

  • You accidentally declared a nested sendEmails() function inside the loop and never called it; removed.

  • Added try/catch so “Sent” is only written when an email is actually sent.

  • Uses your localized headers: Namn, E-postadress.

  • Demonstrates attaching either a native Google file (export to PDF) or a normal file (as blob).

    Corrected script:

    function sendEmails() {
      // Load the spreadsheet data
      const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
      const allData = sheet.getDataRange().getValues();
      const headers = allData[0];
      const rows = allData.slice(1);
    
      // Helper to detect column indices by header name
      const getColIndex = (headerName) => {
        const index = headers.indexOf(headerName);
        if (index === -1) throw new Error(`Header "${headerName}" not found.`);
        return index;
      };
    
      // Adjust to match your sheet headers
      const nameCol = getColIndex('Namn');
      const emailCol = getColIndex('E-postadress');
      const sentCol = getColIndex('Sent');
    
      // Drive file to attach
      // Replace with your actual file ID
      const FILE_ID = '1ezM-QiJ73Ry4xmNMdWHdC-4jXJ4gUHhB';
      const file = DriveApp.getFileById(FILE_ID);
    
      // If it's a Google Doc/Sheet/Slide you want as PDF, use getAs(PDF)
      // Otherwise (e.g., PDF/PNG already), use getBlob()
      let attachmentBlob;
      try {
        // Try exporting to PDF (works for Google Docs/Sheets/Slides)
        attachmentBlob = file.getAs(MimeType.PDF);
      } catch (e) {
        // Fallback: use original blob (works for non-Google files)
        attachmentBlob = file.getBlob();
      }
    
      // Loop rows
      rows.forEach((row, i) => {
        const name = row[nameCol];
        const email = row[emailCol];
        const sent = row[sentCol];
    
        // Skip rows that have been sent already or missing email
        if (!email || sent) return;
    
        const subject = 'Postpartum Checklist';
        const body =
          `Dear ${name},\n\n` +
          `Så härligt att du tar dina första steg mot en positiv postpartum upplevelse. ` +
          `Oavsett om det är din första eller fjärde gång, hoppas jag att du hittar lite trygghet i den här checklistan.\n\n` +
          `Ladda ner och skriv ut den, eller få ditt utskriven exemplar från mig om du valde att bli kontaktad för en första konsultation.\n\n` +
          `Mvh,\nLeila`;
    
        try {
          // Send email with attachment via options object
          MailApp.sendEmail({
            to: email,
            subject,
            body,
            attachments: [attachmentBlob], // you can attach multiple: [blob1, blob2]
            // Optional: htmlBody: '<p>...</p>',
            // Optional: name: 'Your Sender Name',
          });
    
          // Mark as sent with timestamp
          sheet.getRange(i + 2, sentCol + 1).setValue(new Date());
    
          // Optional: be polite to quotas
          Utilities.sleep(200);
        } catch (err) {
          // Log error but do not mark as sent
          console.error(`Failed to send to ${email}: ${err}`);
        }
      });
    }function sendEmails() {
      // Load the spreadsheet data
      const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
      const allData = sheet.getDataRange().getValues();
      const headers = allData[0];
      const rows = allData.slice(1);
    
      // Helper to detect column indices by header name
      const getColIndex = (headerName) => {
        const index = headers.indexOf(headerName);
        if (index === -1) throw new Error(`Header "${headerName}" not found.`);
        return index;
      };
    
      // Adjust to match your sheet headers
      const nameCol = getColIndex('Namn');
      const emailCol = getColIndex('E-postadress');
      const sentCol = getColIndex('Sent');
    
      // Drive file to attach
      // Replace with your actual file ID
      const FILE_ID = '1ezM-QiJ73Ry4xmNMdWHdC-4jXJ4gUHhB';
      const file = DriveApp.getFileById(FILE_ID);
    
      // If it's a Google Doc/Sheet/Slide you want as PDF, use getAs(PDF)
      // Otherwise (e.g., PDF/PNG already), use getBlob()
      let attachmentBlob;
      try {
        // Try exporting to PDF (works for Google Docs/Sheets/Slides)
        attachmentBlob = file.getAs(MimeType.PDF);
      } catch (e) {
        // Fallback: use original blob (works for non-Google files)
        attachmentBlob = file.getBlob();
      }
    
      // Loop rows
      rows.forEach((row, i) => {
        const name = row[nameCol];
        const email = row[emailCol];
        const sent = row[sentCol];
    
        // Skip rows that have been sent already or missing email
        if (!email || sent) return;
    
        const subject = 'Postpartum Checklist';
        const body =
          `Dear ${name},\n\n` +
          `Så härligt att du tar dina första steg mot en positiv postpartum upplevelse. ` +
          `Oavsett om det är din första eller fjärde gång, hoppas jag att du hittar lite trygghet i den här checklistan.\n\n` +
          `Ladda ner och skriv ut den, eller få ditt utskriven exemplar från mig om du valde att bli kontaktad för en första konsultation.\n\n` +
          `Mvh,\nLeila`;
    
        try {
          // Send email with attachment via options object
          MailApp.sendEmail({
            to: email,
            subject,
            body,
            attachments: [attachmentBlob], // you can attach multiple: [blob1, blob2]
            // Optional: htmlBody: '<p>...</p>',
            // Optional: name: 'Your Sender Name',
          });
    
          // Mark as sent with timestamp
          sheet.getRange(i + 2, sentCol + 1).setValue(new Date());
    
          // Optional: be polite to quotas
          Utilities.sleep(200);
        } catch (err) {
          // Log error but do not mark as sent
          console.error(`Failed to send to ${email}: ${err}`);
        }
      });
    }
    
Sign up to request clarification or add additional context in comments.

2 Comments

You've accidentally paste the code twice. Also please check out Generative AI (e.g., ChatGPT) is banned
due to network error ive tried to past but its not workin that's why maybe it pasted 2 times and tnx to let me know for Genrative ai

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.