javascriptgoogle-apps-scripttriggersgoogle-forms

Google Apps script for OTP generation


I tried using a Google Apps script attached to a Google form to generate a one-time password.

The script intends to make the respondent fill out the email ID, leaving the OTP field blank. The submit button triggers the OTP generation and will be sent to the email ID keyed in. Then the respondent edits the response, keys in the OTP, and submits. The latter submission triggers verification of the OTP and displays the success/failure message.

This script is not working as intended. Could anyone help correcting it so it works?

Form Responder Link

Script:

function onSubmit(e) {
  Logger.log("onSubmit triggered");

  var itemResponses = e.response.getItemResponses();
  var emailItem =
    itemResponses.find(item =>
                       item.getItem().getTitle() == "Your Email Address"); // Replace with your email question title

  if (!emailItem) {
    Logger.log("ERROR: Email question NOT found!");
    itemResponses.forEach(itemResponse => Logger.log("Item Title: " + itemResponse.getItem().getTitle()));
    return;
  }

  var email = emailItem.getResponse();
  Logger.log("Email: " + email);

  var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

  if (!emailRegex.test(email)) {
    Logger.log("ERROR: Invalid email address: " + email);
    e.response.withItemResponses().setConfirmationMessage("Invalid email address. Please enter a valid email.");
    return;
  }

  // Get the edit URL
  var editUrl = e.response.getEditResponseUrl();
  Logger.log("Edit URL: " + editUrl);

  var cache = CacheService.getScriptCache();
  cache.put("pending_email", email, 300); // Store email for 5 minutes
  cache.put("edit_url", editUrl, 300); // Store edit URL

  // Generate and send OTP
  var otp = generateOTP();
  cache.put(email + "_otp", otp, 300); // Store OTP for 5 minutes
  sendEmail(email, otp, editUrl); // Send email with OTP and edit URL


  // Instead of setEditResponse, use a confirmation message to prompt for OTP entry
  e.response.withItemResponses().setConfirmationMessage("Thank you for submitting your email. Please check your inbox (and spam folder) for the OTP. Click the link in the email to complete your submission.");

  return;
}

function onFormSubmit(e) {
  Logger.log("onFormSubmit triggered");

  var itemResponses = e.response.getItemResponses();
  var emailItem = itemResponses.find(item => item.getItem().getTitle() == "Your Email Address"); // Replace with your email question title
  var email = emailItem.getResponse();
  var otpQuestion = itemResponses.find(item => item.getItem().getTitle() == "OTP"); // Replace with your OTP question title
  var submittedOtp = otpQuestion ? otpQuestion.getResponse() : null;

  var cache = CacheService.getScriptCache();
  var cachedOtp = cache.get(email + "_otp");

  if (submittedOtp && cachedOtp && submittedOtp == cachedOtp) {
    cache.put(email + "_verified", true, 3600);
    e.response.withItemResponses().setConfirmationMessage("Your email has been verified. Thank you for your submission!");
  } else if (submittedOtp) {
    e.response.withItemResponses().setConfirmationMessage("Incorrect OTP. Please try again.");
  } else {
    e.response.withItemResponses().setConfirmationMessage("Please enter the OTP.");
  }
}

function generateOTP() {
  var otp = Math.floor(100000 + Math.random() * 900000); // 6-digit OTP
  return otp.toString();
}

function sendEmail(email, otp, editUrl) { // Add editUrl parameter
  var subject = "Your OTP for Google Form Verification";
  var body = "Your OTP is: " + otp + "\n\nPlease click the following link to complete your submission: " + editUrl; // Include editUrl

  try {
    MailApp.sendEmail(email, subject, body);
    Logger.log("OTP email sent successfully to: " + email);
  } catch (error) {
    Logger.log("ERROR sending OTP email: " + error);
  }
}

Errors observed:

Head    onSubmit    Trigger    Feb 24, 2025, 3:22:24 PM    1.062 s Failed

Cloud logs
Feb 24, 2025, 3:22:24 PM    Info    onSubmit triggered
Feb 24, 2025, 3:22:24 PM    Info    Email: ahkkcr@hotmail.com
Feb 24, 2025, 3:22:25 PM    Info    Edit URL: https://docs.google.com/forms/d/e/1FAIpQLSdtWPCzDm92Tah34gnj4UZHiZgQ22L6nQPxC5LrnwDCoUphsA/viewform?edit2=2_ABaOnud9q2OpMIXEeE6nvxwkIxPCr6JbP-5y9OQJoLoNKEN2va_vWQLR-nQZ8QauOy8iPHw
Feb 24, 2025, 3:22:25 PM    Info    OTP email sent successfully to: ahkkcr@hotmail.com
Feb 24, 2025, 3:22:25 PM    Error    TypeError: e.response.withItemResponses is not a function
                                        at onSubmit(Code:39:14)

Head    onFormSubmit    Trigger    Feb 24, 2025, 3:22:22 PM    1.267 s Failed

Cloud logs
Feb 24, 2025, 3:22:22 PM    Info    onFormSubmit triggered
Feb 24, 2025, 3:22:23 PM    Error    TypeError: e.response.withItemResponses is not a function
                                        at onFormSubmit(Code:62:16)

>TypeError: e.response.withItemResponses is not a function
                                    at onFormSubmit(Code:62:16)

Triggers I added:

Triggers


Solution

  • e.response.withItemResponses().setConfirmationMessage("...")
    

    Here,

    TypeError: e.response.withItemResponses is not a function at onFormSubmit(Code:62:16)

    setConfirmationMessage is a method of class Form. To get a Form from the event object e, use e.source. So, you can use

    e.source.setConfirmationMessage("some message")