在Google Apps Script中检查电子邮件地址是否有效

8
我正在使用Google Spreadsheets的内置API进行脚本编写,以发送一些预订确认信息。如果有人填写了无效的电子邮件,目前我的脚本会停止运行。我希望它只保存一些未被通知的客人数据列表,然后继续循环处理预订。
这是我的当前代码(简化版):
// The variables email, subject and msg are populated.
// I've tested that using Browser.msgBox(), and the correct column values are
// found and used

// The script breaks here, if an incorrect email address has been filled in
MailApp.sendEmail(email, subject, msg)

根据文档MailApp类只有发送邮件和检查每日配额两种方法,没有关于检查有效电子邮件地址的内容,因此我不知道这个类接受请求必须满足什么条件,因此无法编写验证程序。

1
如何使用简单的电子邮件验证正则表达式呢?\b[A-Z0-9._%-]+@[A-Z0-9.-]+.[A-Z]{2,4}\b - rkg
@Ravi:我可以做类似的事情,但由于API调用在无效地址上中断,我非常想知道电子邮件必须满足的确切标准,并能够事先验证... - Tomas Aschan
嗯...如果是无效的电子邮件,sendEmail会抛出特定的异常吗? - rkg
2
这个Wiki页面似乎相当详尽地回答了这个问题。如果sendMail在任何“合法”格式中失败,那么应该将其报告为功能请求。 编辑:您还可以在其周围进行try-catch,并存储导致错误的电子邮件地址。 - Anton Soradoi
4个回答

14
如果您需要预先验证电子邮件地址,请在 Google 云端硬盘中创建一个空白电子表格。然后,运行下面的函数,将 testSheet 变量更改为指向您创建的电子表格。该函数将进行简单的正则表达式测试以捕获格式不正确的电子邮件地址,然后尝试将其作为查看者暂时添加到电子表格上来检查地址是否有效。如果可以添加,则必须是有效的。
function validateEmail(email) {
  var re = /\S+@\S+\.\S+/;
  if (!re.test(email)) {
    return false;
  } else {
    var testSheet = SpreadsheetApp.openById(arbitrarySpreadsheetInYourDrive);
    try {
      testSheet.addViewer(email);
    } catch(e) {
      return false;
    }
    testSheet.removeViewer(email);
    return true;
  }
}

来自如何在JavaScript中验证电子邮件地址?的正则表达式。


1
我曾考虑使用类似的解决方案,但我使用的是驱动器服务DriveApp而不是电子表格服务SpreadsheetApp,使用DriveApp服务会导致向查看者发送通知电子邮件。然而,在查看了这个答案之后,我发现SpreadsheetApp不会发送电子邮件通知。好答案! - alejandro
1
您也可以创建一个临时电子表格,然后将其删除,而不是为此目的在Drive中保留一个电子表格。 - Janine White

6
保持冷静,捕获并记录异常,然后继续执行:
try {
  // do stuff, including send email
  MailApp.sendEmail(email, subject, msg)
} catch(e) {
  Logger.log("Error with email (" + email + "). " + e);
}

这个问题已经很老了 - 我需要用那个应用程序发送的所有电子邮件都已经发送了。但是如果我必须再次这样做,这绝对是我会采取的方法。 - Tomas Aschan
我认为在JavaScript中无法指定要捕获的异常类型。 - CaptainNemo
这会引发什么样的异常?如果您向无效的电子邮件地址发送过多邮件,您将被禁止。 - User
问题在于,其他异常,如“Service invoked too many times for one day: email.”也被归类为格式错误的电子邮件地址。 - User
以下是我捕获的一些异常: 无法发送电子邮件:没有收件人无效的电子邮件:abc@abc此外,为了避免配额超载,您可以使用 MailApp.getRemainingDailyQuota() - flo5783
有时脚本会在 Logger.log 处卡住,你有什么想法吗? - Vladimir Obrizan

0

另外,避免在脚本中检查电子邮件并摆脱配额损失或 try-catch 等。我使用这样的方式,在用户尝试发送电子邮件时,通过向他发送一封电子邮件进行登录并获取有效的电子邮件:

private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
    try {
        GoogleSignInAccount account = completedTask.getResult(ApiException.class);

       String s = account.getEmail(); // here is the valid email.
                       
    } catch (ApiException e) {
        // The ApiException status code indicates the detailed failure reason.
        // Please refer to the GoogleSignInStatusCodes class reference for more information.
        Log.w(TAG, "signInResult:failed code=" + e.getStatusCode());
       
    }
}

完整过程在此处。


0

这个回答比问题提出的时间晚得多,但我基于remitnotpaucity的答案,在他的答案评论中进行了附带。它基本上做了同样的事情,将电子邮件添加到电子表格中并捕获错误,但在我的情况下,它创建一个新的电子表格,尝试添加用户,然后在尝试添加用户后删除电子表格。在两种情况下,无论电子邮件是有效的还是无效的,它都会删除新创建的电子表格。

需要注意的一些事项:

  1. 我对正则表达式不太熟悉,所以我只检查传入函数的电子邮件中是否包含@符号,而不检查空格。
  2. 即使它通过了第一个if语句,即使它不是有效的电子邮件,仍然会抛出并捕获错误,因为Google仍然会发现它不是有效的电子邮件,使第一个if语句变得多余。
  3. 如果您要验证公司外部的电子邮件,我不确定它会如何反应,因此请提前注意。
  4. 此验证方法需要几秒钟,因为您正在创建然后在单个函数内删除电子邮件,所以比 remitnotpaucity's 更长一些。
  5. 最重要的是,如果可以的话,我建议使用API。 我相信this one应该完全可以使用,并且应该是免费的,但可能需要额外的努力才能与GAS配合使用。
function validateEmail(email){
    let ss = SpreadsheetApp.openByUrl(SpreadsheetApp.create('Email Validation Spreadsheet', 1, 1).getUrl())
    if(!new RegExp('[@]').test(email)){
      return false
    } else{
      try{
        ss.addViewer(email)
      } catch(e){
        setTrashed()
        return false
      }
      setTrashed()
      return true
    }
    function setTrashed(){
      DriveApp.getFilesByName('Email Validation Spreadsheet').next().setTrashed(true)
    }
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接