You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

App Script与JavaScript的CORS跨域问题求助

解决Google Apps Script doPost接口的CORS问题

我有一个能生成HTML文件的JavaScript脚本,想把生成的HTML文件发送到指定邮箱,于是写了下面这个App Script的doPost接口:

function doPost(e) {
  
  let finalOutput = {}; 
   const headers = {
    "Access-Control-Allow-Origin": "*", 
    "Access-Control-Allow-Methods": "POST, OPTIONS", // Specify allowed methods
    "Access-Control-Allow-Headers": "*" // Specify allowed headers
  };
  
  try {
    // 1. Récupération des deux paramètres principaux
    const rapportHTML = e.parameters.htmlContent; 
    const destinataires = e.parameters.destinatairesContainer; 
    
    console.log( "Rapport Html : " + rapportHTML + "\n" + "Destinataires :" + destinataires );

    // Récupération des données pour le sujet
    const ligue = e.parameters.ligue || 'Not specified'; 
    const categorie = e.parameters.categorie || 'Not Specified';
    const matchDomicile = e.parameters.match_domicile || 'Unknown';
    const matchVisiteur = e.parameters.match_visiteur || 'Unknown'; 
    
    // 🛑 ADRESSE D'EXPÉDITION (Alias) (Optionnel - Si nécessaire pour GmailApp)
    const aliasExpediteur = ''; // Ex: 'ne-pas-repondre@votredomaine.com'

    if (!rapportHTML || !destinataires) {
      throw new Error("Contenu du rapport (htmlContent) ou Destinataires (destinatairesContainer) manquants.");
    }
    
    // 2. Construction du sujet
    const subject = `Rapport d'Expulsion: ${matchDomicile} vs ${matchVisiteur} (${ligue} / ${categorie})`;
    
    // 3. Configuration de l'e-mail
    const emailOptions = {
      to: destinataires, 
      subject: subject,
      htmlBody: rapportHTML
    };
    
    if (aliasExpediteur) {
      emailOptions.from = aliasExpediteur;
    }

    // 4. Envoi de l'e-mail avec GMAILAPP
    GmailApp.sendEmail(emailOptions);

    // 5. Réponse SUCCESS
    finalOutput = {
        success: true,
        message: `E-Mail sent to : ${destinataires}`
    };

  } catch (error) {
    // 6. Réponse ERREUR
    finalOutput = {
        success: false,
        error: "Error sending Email: " + error.message,
    };
  }

  // 7. FIX CORS (LIGNE CORRIGÉE ET SÉPARÉE)


   return ContentService.createTextOutput(JSON.stringify(finalOutput))
      .setMimeType(ContentService.MimeType.JSON)
      .addCORSHeaders(headers); // Add CORS headers to error responses as well
  
  return finalOutput; 
}


function addCORSHeaders(response, headers) {  
   for (const header in headers) {     
    response.addHeader(header, headers[header]);  
     }   
     return response; 
     }

但每次通过网页按钮触发邮件发送时,都会出现如下CORS错误:

Access to fetch at 'https://script.google.com/macros/s/AKfycbxHm00gB_Uiv7lK78dDW68cBeFkXz_84G4Q4eJcBIV2gZ1Yowo1cqTgeAr-9kG_rOEB/exec' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

我试过加setAccessControlAllowOrigin('*')但没用,现在卡壳了,求解决办法。


问题原因及解决步骤

1. 必须处理OPTIONS预检请求

浏览器发送POST请求前,会先发送OPTIONS预检请求确认服务器是否允许跨域请求。你的代码没处理这个请求,直接返回了POST的响应,导致预检失败,触发CORS错误。

2. 修复CORS头的设置方式

你自定义的addCORSHeaders函数没被正确调用,而且Google Apps Script的ContentService已经提供了更简单的方法设置CORS头,不用自己循环添加。

修改后的完整代码

function doPost(e) {
  let finalOutput = {};

  // 先处理OPTIONS预检请求
  if (e.method === 'OPTIONS') {
    return ContentService.createTextOutput('')
      .setMimeType(ContentService.MimeType.TEXT)
      .setAccessControlAllowOrigin('*')
      .setAccessControlAllowMethods('POST, OPTIONS')
      .setAccessControlAllowHeaders('*');
  }

  try {
    // 1. 获取核心参数
    const rapportHTML = e.parameters.htmlContent;
    const destinataires = e.parameters.destinatairesContainer;

    console.log("Rapport Html : " + rapportHTML + "\n" + "Destinataires :" + destinataires);

    // 获取邮件主题相关数据
    const ligue = e.parameters.ligue || 'Not specified';
    const categorie = e.parameters.categorie || 'Not Specified';
    const matchDomicile = e.parameters.match_domicile || 'Unknown';
    const matchVisiteur = e.parameters.match_visiteur || 'Unknown';

    // 发件人别名(可选)
    const aliasExpediteur = ''; // 示例: 'ne-pas-repondre@votredomaine.com'

    if (!rapportHTML || !destinataires) {
      throw new Error("Contenu du rapport (htmlContent) ou Destinataires (destinatairesContainer) manquants.");
    }

    // 2. 构建邮件主题
    const subject = `Rapport d'Expulsion: ${matchDomicile} vs ${matchVisiteur} (${ligue} / ${categorie})`;

    // 3. 配置邮件参数
    const emailOptions = {
      to: destinataires,
      subject: subject,
      htmlBody: rapportHTML
    };

    if (aliasExpediteur) {
      emailOptions.from = aliasExpediteur;
    }

    // 4. 发送邮件
    GmailApp.sendEmail(emailOptions);

    // 5. 成功响应
    finalOutput = {
      success: true,
      message: `E-Mail sent to : ${destinataires}`
    };

  } catch (error) {
    // 6. 错误响应
    finalOutput = {
      success: false,
      error: "Error sending Email: " + error.message,
    };
  }

  // 7. 返回带CORS头的JSON响应
  return ContentService.createTextOutput(JSON.stringify(finalOutput))
    .setMimeType(ContentService.MimeType.JSON)
    .setAccessControlAllowOrigin('*');
}

额外注意事项

  • 部署App Script时,要确保部署类型是Web应用,且权限设置为“任何人,甚至匿名”(如果你的场景允许)。
  • 测试时尽量避免直接打开本地HTML文件(origin为null的情况),可以把HTML放到本地服务器(比如用Python的http.server)或者线上托管平台测试,这样origin会是合法的域名。

内容的提问来源于stack exchange,提问作者Rapport Dexpulsion Rive-Sud R

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 06:34:57