Search code examples
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 and keys in the otp and then submits. The latter submission triggers verification of otp and displays the success/failure message.

This script is not working as intended Could enyone 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,

    • e is the form submission event object
    • e.response returns FormResponse object
    • FormResponse object doesn't have the method withItemResponses. Therefore e.response.withItemResponses returns undefined.
    • undefined is not a function and therefore you cannot call it. So, you receive the error,

    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")