dwyl / learn-to-send-email-via-google-script-html-no-server

:email: An Example of using an HTML form (e.g: "Contact Us" on a website) to send Email without a Backend Server (using a Google Script) perfect for static websites that need to collect data.
GNU General Public License v2.0
3.15k stars 909 forks source link

Getting an Error: Script function not found: doGet even though a post request is made #458

Closed StylianosThomas closed 2 weeks ago

StylianosThomas commented 1 month ago

Hi, I'm having an issue implementing a slightly different version of this repo. I made a clone of this project: https://github.com/rampatra/wedding-website, which is using the same system as yours to populate a Google Sheet with a website form data via a Google Script published as a Web app. I made no changes other that swapping out the default email and Webapp's URL with mine.

Here is part of the index.html responsible for the form fields:

<form id="rsvp-form" class="rsvp-form" action="" method="POST">
    <div class="row">
        <div class="col-md-6 col-sm-6">
            <div class="form-input-group">
                <i class="fa fa-envelope"></i>
                <input type="email" name="email" class="" placeholder="Your email" required>
            </div>
        </div>
        <div class="col-md-6 col-sm-6">
            <div class="form-input-group">
                <i class="fa fa-user"></i>
                <input name="name" class="" placeholder="Your name" required>
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-md-6 col-sm-6">
            <div class="form-input-group">
                <i class="fa fa-users"></i>
                <input type="number" name="extras" class="" min="0" max="4" placeholder="Husband/Wife or kids" required>
            </div>
        </div>
        <div class="col-md-6 col-sm-6">
            <div class="form-input-group">
                <i class="fa fa-key"></i>
                <input type="number" name="invite_code" id="invite_code" class="" min="0" placeholder="Invite code" required>
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-md-12" id="alert-wrapper"></div>
    </div>
    <button class="btn-fill rsvp-btn">
        Yes, that's me!
    </button>
</form>

Here is part of the javascript that is responsible for making the post request to the webapp:

$('#rsvp-form').on('submit', function (e) {
    e.preventDefault();
    var data = $(this).serialize();

    $('#alert-wrapper').html(alert_markup('info', '<strong>Just a sec!</strong> We are saving your details.'));

    if (MD5($('#invite_code').val()) !== 'b0e53b10c1f55ede516b240036b88f40'
        && MD5($('#invite_code').val()) !== '2ac7f43695eb0479d5846bb38eec59cc') {
        $('#alert-wrapper').html(alert_markup('danger', '<strong>Sorry!</strong> Your invite code is incorrect.'));
    } else {
        $.post('https://script.google.com/macros/s/AKfycbzUqz44wOat0DiGjRV1gUnRf4HRqlRARWggjvHKWvqniP7eVDG-/exec', data)
            .done(function (data) {
                console.log(data);
                if (data.result === "error") {
                    $('#alert-wrapper').html(alert_markup('danger', data.message));
                } else {
                    $('#alert-wrapper').html('');
                    $('#rsvp-modal').modal('show');
                }
            })
            .fail(function (data) {
                console.log(data);
                $('#alert-wrapper').html(alert_markup('danger', '<strong>Sorry!</strong> There is some issue with the server. '));
            });
    }
});

And finally here is the Google Appscript code of the webapp

var TO_ADDRESS = "youremailaddress@gmail.com"; // email to send the form data to

/**
 * This method is the entry point.
 */
function doPost(e) {

  try {
    Logger.log(e); // the Google Script version of console.log see: Class Logger

    var mailData = e.parameters; // just create a slightly nicer variable name for the data

    if (mailData.invite_code != "271117") { // validate invite code before saving data
      Logger.log("Incorrect Invite Code");
      return ContentService
          .createTextOutput(JSON.stringify({"result":"error", "message": "Sorry, your invite code (" + mailData.invite_code + ") is incorrect."}))
          .setMimeType(ContentService.MimeType.JSON);
    }

    record_data(e);

    MailApp.sendEmail({
      to: TO_ADDRESS,
      subject: "A new guest RSVP'd for your wedding",
      replyTo: String(mailData.email), // This is optional and reliant on your form actually collecting a field named `email`
      htmlBody: formatMailBody(mailData)
    });

    return ContentService    // return json success results
          .createTextOutput(JSON.stringify({"result":"success","data": JSON.stringify(e.parameters) }))
          .setMimeType(ContentService.MimeType.JSON);
  } catch(error) { // if error return this
    Logger.log(error);
    return ContentService
          .createTextOutput(JSON.stringify({"result":"error", "message": "Sorry, there is an issue with the server."}))
          .setMimeType(ContentService.MimeType.JSON);
  }
}

/**
 * This method inserts the data received from the html form submission
 * into the sheet. e is the data received from the POST
 */
function record_data(e) {
  Logger.log(JSON.stringify(e)); // log the POST data in case we need to debug it
  try {
    var doc     = SpreadsheetApp.getActiveSpreadsheet();
    var sheet   = doc.getSheetByName('responses'); // select the responses sheet
    var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
    var nextRow = sheet.getLastRow()+1; // get next row
    var row     = [ new Date().toUTCString() ]; // first element in the row should always be a timestamp
    // loop through the header columns
    for (var i = 1; i < headers.length; i++) { // start at 1 to avoid Timestamp column
      if(headers[i].length > 0) {
        row.push(e.parameter[headers[i]]); // add data to row
      }
    }
    // more efficient to set values as [][] array than individually
    sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
  }
  catch(error) {
    Logger.log(error);
    Logger.log(e);
    throw error;
  }
  finally {
    return;
  }
}

/**
 * This method is just to prettify the email.
 */
function formatMailBody(obj) { // function to spit out all the keys/values from the form in HTML
  var result = "";
  for (var key in obj) { // loop over the object passed to the function
    result += "<h4 style='text-transform: capitalize; margin-bottom: 0'>" + key + "</h4><div>" + obj[key] + "</div>";
    // for every key, concatenate an `<h4 />`/`<div />` pairing of the key name and its value, 
    // and append it to the `result` string created at the start.
  }
  return result; // once the looping is done, `result` will be one long string to put in the email body
}

The problem that I'm facing is that when submitting the form via the website, nothing is populated on the Google Sheet, I receive no email and when going to the WebApp via browser, I get an error: "Script function not found: doGet", which is weird since I make a post request, not a get one.

Any help would be highly appreciated.

AMC-ai commented 1 month ago

Hmm it's been a while since I've looked at the code. But I'll take a look tomorrow and see if there's anything that sticks out to me.

On Sat, Nov 2, 2024, 11:13 PM Stylianos Thomas @.***> wrote:

Hi, I'm having an issue implementing a slightly different version of this repo. I made a clone of this project: https://github.com/rampatra/wedding-website, which is using the same system as yours to populate a Google Sheet with a website form data via a Google Script published as a Web app. I made no changes other that swapping out the default email and Webapp's URL with mine.

Here is part of the index.html responsible for the form fields:

Here is part of the javascript that is responsible for making the post request to the webapp:

$('#rsvp-form').on('submit', function (e) { e.preventDefault(); var data = $(this).serialize();

$('#alert-wrapper').html(alert_markup('info', '<strong>Just a sec!</strong> We are saving your details.'));

if (MD5($('#invite_code').val()) !== 'b0e53b10c1f55ede516b240036b88f40'
    && MD5($('#invite_code').val()) !== '2ac7f43695eb0479d5846bb38eec59cc') {
    $('#alert-wrapper').html(alert_markup('danger', '<strong>Sorry!</strong> Your invite code is incorrect.'));
} else {
    $.post('https://script.google.com/macros/s/AKfycbzUqz44wOat0DiGjRV1gUnRf4HRqlRARWggjvHKWvqniP7eVDG-/exec', data)
        .done(function (data) {
            console.log(data);
            if (data.result === "error") {
                $('#alert-wrapper').html(alert_markup('danger', data.message));
            } else {
                $('#alert-wrapper').html('');
                $('#rsvp-modal').modal('show');
            }
        })
        .fail(function (data) {
            console.log(data);
            $('#alert-wrapper').html(alert_markup('danger', '<strong>Sorry!</strong> There is some issue with the server. '));
        });
}

});

And finally here is the Google Appscript code of the webapp

var TO_ADDRESS = @.***"; // email to send the form data to

/**

  • This method is the entry point. */ function doPost(e) {

    try { Logger.log(e); // the Google Script version of console.log see: Class Logger

    var mailData = e.parameters; // just create a slightly nicer variable name for the data

    if (mailData.invite_code != "271117") { // validate invite code before saving data Logger.log("Incorrect Invite Code"); return ContentService .createTextOutput(JSON.stringify({"result":"error", "message": "Sorry, your invite code (" + mailData.invite_code + ") is incorrect."})) .setMimeType(ContentService.MimeType.JSON); }

    record_data(e);

    MailApp.sendEmail({ to: TO_ADDRESS, subject: "A new guest RSVP'd for your wedding", replyTo: String(mailData.email), // This is optional and reliant on your form actually collecting a field named email htmlBody: formatMailBody(mailData) });

    return ContentService // return json success results .createTextOutput(JSON.stringify({"result":"success","data": JSON.stringify(e.parameters) })) .setMimeType(ContentService.MimeType.JSON); } catch(error) { // if error return this Logger.log(error); return ContentService .createTextOutput(JSON.stringify({"result":"error", "message": "Sorry, there is an issue with the server."})) .setMimeType(ContentService.MimeType.JSON); } }

/**

  • This method inserts the data received from the html form submission
  • into the sheet. e is the data received from the POST */ function record_data(e) { Logger.log(JSON.stringify(e)); // log the POST data in case we need to debug it try { var doc = SpreadsheetApp.getActiveSpreadsheet(); var sheet = doc.getSheetByName('responses'); // select the responses sheet var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0]; var nextRow = sheet.getLastRow()+1; // get next row var row = [ new Date().toUTCString() ]; // first element in the row should always be a timestamp // loop through the header columns for (var i = 1; i < headers.length; i++) { // start at 1 to avoid Timestamp column if(headers[i].length > 0) { row.push(e.parameter[headers[i]]); // add data to row } } // more efficient to set values as [][] array than individually sheet.getRange(nextRow, 1, 1, row.length).setValues([row]); } catch(error) { Logger.log(error); Logger.log(e); throw error; } finally { return; } }

/**

  • This method is just to prettify the email. */ function formatMailBody(obj) { // function to spit out all the keys/values from the form in HTML var result = ""; for (var key in obj) { // loop over the object passed to the function result += "

    " + key + "

    " + obj[key] + "
    "; // for every key, concatenate an <h4 />/<div /> pairing of the key name and its value, // and append it to the result string created at the start. } return result; // once the looping is done, result will be one long string to put in the email body }

The problem that I'm facing is that when submitting the form via the website, nothing is populated on the Google Sheet, I receive no email and the only execution log that I get is: "Script function not found: doGet", which is weird since I make a post request, not a get one.

Any help would be highly appreciated.

— Reply to this email directly, view it on GitHub https://github.com/dwyl/learn-to-send-email-via-google-script-html-no-server/issues/458, or unsubscribe https://github.com/notifications/unsubscribe-auth/AMXBEHUS2VB5KMY4VGEVTDLZ6WPGBAVCNFSM6AAAAABRCLDHQOVHI2DSMVQWIX3LMV43ASLTON2WKOZSGYZTAOJVGMZTGNQ . You are receiving this because you are subscribed to this thread.Message ID: <dwyl/learn-to-send-email-via-google-script-html-no-server/issues/458@ github.com>