Sendgrid-nodejs: 发送批量邮件时出现错误401未经授权

创建于 2019-08-20  ·  26评论  ·  资料来源: sendgrid/sendgrid-nodejs

我在Google Cloud Functions上使用@ sendgrid / mail模块。

我的邮件格式如下:

{
    to: user.email,
    from: user.fromail,
    cc: user.tl_email,
    subject: 'Test',
    html: setTemplate(),
    attachments: [{
     filename: 'test.png',
     content: test,
     content_id: 'test',
     disposition: 'inline'
   },
   ...]
  };

我有一系列带有不同“至”和不同html电子邮件的邮件。

当我使用sgMail.send(emailsArray)而user.email只是我时,邮件将被发送,因此api密钥可以正常工作。

当我使用sgMail.send(emailsArray)和user.email彼此不同时,出现此错误:

{ Error: Unauthorized
    at Request.http [as _callback] (node_modules/@sendgrid/client/src/classes/client.js:124:25)
    at Request.self.callback (node_modules/request/request.js:185:22)
    at emitTwo (events.js:126:13)
    at Request.emit (events.js:214:7)
    at Request.<anonymous> (node_modules/request/request.js:1161:10)
    at emitOne (events.js:116:13)
    at Request.emit (events.js:211:7)
    at IncomingMessage.<anonymous> (node_modules/request/request.js:1083:12)
    at Object.onceWrapper (events.js:313:30)
    at emitNone (events.js:111:20)
  code: 401,
  message: 'Unauthorized',
  response: 
   { headers: 
      { server: 'nginx',
        date: 'Fri, 16 Aug 2019 08:00:04 GMT',
        'content-type': 'application/json',
        'content-length': '74',
        connection: 'close',
        'access-control-allow-origin': 'https://sendgrid.api-docs.io',
        'access-control-allow-methods': 'POST',
        'access-control-allow-headers': 'Authorization, Content-Type, On-behalf-of, x-sg-elas-acl',
        'access-control-max-age': '600',
        'x-no-cors-reason': 'https://sendgrid.com/docs/Classroom/Basics/API/cors.html' },
     body: undefined } }

有什么帮助吗?

技术细节:

“ @ sendgrid / mail”:“ ^ 6.4.0”,
Node.js版本:“ ^ 8.0.0”

easy help wanted community enhancement

最有用的评论

更多内容:我们已经使用此软件包近两年了。 2月25日是我们有史以来第一次。 然后是3月15日和3月17日,今天是今天的两次。 这个问题没有解决,而且似乎越来越严重。

所有26条评论

你好

我在这里有一个非常类似的SDK问题(使用NodeJS SDK 6.4.0),客户支持将我发送到这里,因为他们认为这是SDK本身的问题。 我经常在同一台服务器上同时发送电子邮件,但API调用却得到了不同的答案。

范例:

  • 电子邮件已发送到[email protected],且API密钥为YYY ==>接受电子邮件
  • 电子邮件已发送到[email protected],且API密钥YYY ==>被拒绝,错误401,错误消息与上面相同
  • 电子邮件已发送到[email protected],且API密钥为YYY ==>接受电子邮件

这是关于某天的一些数字,当我们试图使用SDK调用SendGrid发送多封电子邮件时:

  • 我们尝试发送70封电子邮件(使用相同的API密钥)
  • 该电子邮件中的每一个在“收件人”字段中都有1个电子邮件地址,在“密件抄送”字段中有2个电子邮件地址
  • 这些API调用是由18种不同的服务器(实际上是18种不同的Heroku dynos,其中一些可能在同一服务器上)进行的
  • API接受了52个调用,并以“ 401未经授权的错误”拒绝了18个调用

    • 在这18个因401错误而被拒绝的应用中,有7个以“错误体”为“未定义”被拒绝,而11个以“错误体”为“ [无法验证”,字段:null,帮助:null}]}被拒绝。

  • 一切都在06:00:00 AM和06:00:02 AM之间执行
  • 使用的源代码使用SDK方法sgMail.setApiKey(SENDGRID_API_KEY)设置密钥(对于每个调用都设置得很好,我看到读取字段sgMail.client.apiKey),并且我们使用了SDK方法sgMail.sendMultiple(email)发送电子邮件。

尝试使用同一API密钥进行多次调用时,SDK是否会出现并发问题?

这是使用的代码:

const sgMail = require('@sendgrid/mail');

const SENDGRID_API_KEY = process.env.SENDGRID_API_KEY;
const SENDGRID_MY_TEMPLATE_ID = process.env.SENDGRID_MY_TEMPLATE_ID;

sgMail.setApiKey(SENDGRID_API_KEY);

class Mail {
  static async sendReport(recipientEmails, data) {
    const email = {
      to: recipientEmails,
      bcc: ['[email protected]', '[email protected]'],
      from: {
        email: '[email protected]',
        name: 'MyCompany',
      },
      replyTo: '[email protected]',
      template_id: SENDGRID_MY_TEMPLATE_ID,
      asm: {
        group_id: 1234,
      },
      dynamic_template_data: data,
    };

    try {
      await sgMail.sendMultiple(email);
    } catch (e) {
      console.log('ERROR Sending Report', e);
      console.log('ERROR Sending Report', e.toString());
      console.log('ERROR Sending Report', e.response.body);
      throw e;
    }
  }
}

我确认对我来说也是一样。 某些请求被接受,但其他请求得到401未经授权。
但是,实际上不可能理解401的原因,因为它似乎是随机的,并且不依赖于我的代码。

我尝试了多种更改:

  • 使用sgMail.send而不是sgMail.sendMultiple
  • 在两次通话之间增加了半秒的小延迟
  • 硬API密钥
const sgMail = require('@sendgrid/mail');
const SENDGRID_MY_TEMPLATE_ID = process.env.SENDGRID_MY_TEMPLATE_ID;
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

sgMail.setApiKey('HARDCODED_API_KEY');

class Mail {
  static async sendReport(recipientEmails, data) {
    const email = {
      to: recipientEmails,
      bcc: ['[email protected]', '[email protected]'],
      from: {
        email: '[email protected]',
        name: 'MyCompany',
      },
      replyTo: '[email protected]',
      template_id: SENDGRID_MY_TEMPLATE_ID,
      asm: {
        group_id: 1234,
      },
      dynamic_template_data: data,
    };

    try {
      await sgMail.send(email);
      await sleep(500);

    } catch (e) {
      console.log('ERROR Sending Report', e);
      console.log('ERROR Sending Report', e.toString());
      console.log('ERROR Sending Report', e.response.body);
      throw e;
    }
  }
}

但是同样的问题...

奇怪的是,相应的源代码看起来很干净,因此,如果没有SendGrid开发人员访问API代码的帮助,就很难进行故障排除...

@yoagauthier您是否已解决此问题?
我认为开发人员团队不会为我们提供帮助。

@ francesco-clementi-bip不,我们可能很快就会切换邮件提供商,此存储库似乎已经死了,支持对于理解该问题不是很有帮助。

我现在还不确定问题是否出自SDK:我尝试直接针对REST API进行编码,但我仍然对/mail/send进行API调用,但被401拒绝(大约10%),而大多数都使用相同的配置(大约90%)和相同的API密钥。 就我而言,我怀疑是因为这些调用是在不同的服务器上同时完成的,而auth服务器可能无法处理它。

我的代码:

const axios = require('axios');
const {
  SENDGRID_MY_TEMPLATE_ID,
  SENDGRID_API_KEY,
} = process.env;

class SendGridClient {
  constructor() {
    this.axiosInstance = axios.create({
      baseURL: 'https://api.sendgrid.com/v3',
      headers: {
        Authorization: `Bearer ${SENDGRID_API_KEY}`,
      },
    });
  }

  async sendMail(toEmail, data) {
    const email = {
      personalizations: [
        {
          to: [
            {
              email: toEmail,
            },
          ],
          dynamic_template_data: data,
        },
      ],
      from: {
        email: '[email protected]',
        name: 'MyCompany',
      },
      reply_to: {
        email: '[email protected]',
        name: 'MyCompany',
      },
      template_id: SENDGRID_MY_TEMPLATE_ID,
      asm: {
        group_id: 1234,
      },
    };

    try {
        await this.axiosInstance.post('/mail/send', email);
    } catch (e) {
      console.log('ERROR Sending Report', e);
      console.log('ERROR Sending Report', e.response.data);
      throw e;
    }
  }
}

module.exports = SendGridClient;

谢谢@yoagauthier
我试图直接使用api并获得与您相同的结果。
我们下周将更改供应商,因为sendgrid尚未准备好用于生产。
祝你今天愉快

我们也随机出现此问题(可能一个月两次): 401 Unauthorized无缘无故。

同样的问题。 我用了Sendgrid几年了。 并且最近开始出现401错误。 客户服务是没有用的。

同样在这里,只是在开发人员模式下(低容量测试)开始随机获取这些错误。 什么都没有改变,只是随机地开始出现这些错误。

我遇到了同样的问题,我删除了sendgrid .env并将SENDGRID_API_KEY声明为变量

const sgMail = require('@sendgrid/mail');
const SENDGRID_API_KEY='{api_key};
sgMail.setApiKey(SENDGRID_API_KEY);

如果在直接访问API时看到类似的行为,则该库将无法为您解决问题。

也就是说,有可能根据您的环境未正确加载API密钥。 将API密钥粘贴到.env文件中并进行采购只是将其加载的一种方法,但是还有其他方法,这仅取决于您的环境如何最好地配置env var。

如果您将API密钥设置为空字符串,我们在该库中所做的就是更新基础客户端以引发异常,这将表明您的环境存在问题,并且无法快速进行调试。

我将把这个问题留给任何想实施最后一部分的人。

此外,我已经确认API密钥始终以前缀SG.开头,因此在调用setApiKey()时也可以用于进一步理清传入的API密钥。

在短时间内向不同的收件人发送几封电子邮件时,+ 1存在相同的问题。
使用heroku和通过env变量传递密钥,不知道为什么env变量在大多数时间都可以工作并且env变量没有其他问题,为什么不可用。

@ childish-sambino是否有避免这种问题的可靠方法? 也许在同一MailData对象中可以发送的电子邮件数量上限? 谢谢!

@dockleryxk如果您看到看似随机的Unauthorized 401 s并且您的API密钥已正确加载,则我不知道根本原因是什么,并且可能不是该lib中应处理的东西。 SendGrid支持提供了可帮助调试此类问题的工具。

更改我之前关于保持此状态为打开以跟踪处理空/未定义/空/空API密钥的评论。 让我们使用https://github.com/sendgrid/sendgrid-nodejs/issues/1068跟踪该工作。

@ childish-sambino我不同意您的结论以结束此问题。 你在吹嘘什么,但是你有证据吗? 这个库更有可能是一个问题。

@crascher为帮助调试所遇到的问题,是否已看到(例如通过日志记录)在看到401 s时发送了正确的API密钥? 重新输入相同的请求会导致相同的错误吗? 直接调用API时是否看到相同的问题?

@ childish-sambino感谢您的回复。 为了提供更多上下文,我的API密钥是硬编码的(在我的情况下这无关紧要)。
我将在相同的sendMail调用中收到此错误。 具体来说,电子邮件将成功发送给某些收件人,但一个或多个不会发送并收到此错误。 在to字段中总是很好(我在这里只收到一封电子邮件),但是对我来说,出现多封电子邮件的cc字段是多问题。

我试图重新创建该错误,但从未发生。 只是在产品环境中,我不能简单地重新发送它们,因为这会导致一些恼人的客户。

@ childish-sambino我在sendMail逻辑的回调方法中添加了一个错误发生时执行另一个sendMail的方法。 邮件已发送给我,并且可以正常工作。
我没有抄送字段。 可能是返回的代码401错误,或者此库丢失了令牌或api引发了问题。

您打算再次打开这张票吗? 对我来说还没有解决。

更多内容:我们已经使用此软件包近两年了。 2月25日是我们有史以来第一次。 然后是3月15日和3月17日,今天是今天的两次。 这个问题没有解决,而且似乎越来越严重。

@dockleryxk @crascher听起来像是同样的问题:表面上的401 s看起来是随机的,即使您的环境没有其他变化。 我非常怀疑该库本身已经审查了代码并且没有发现API密钥方面的复杂性是一个问题。

我提出的打开支持通知单的建议仍然有效(支持不会在此处监视问题,工程师会这样做)。 如果您可以为他们提供有关请求失败时间的详细信息,则任何其他详细信息将有助于对其进行跟踪。 如果这样做没有帮助或您没有及时收到回复,请告诉我。 我们正在努力提高这些论坛的响应速度。

最后,该库将很快迁移基础HTTP客户端(https://github.com/sendgrid/sendgrid-nodejs/issues/1042),我们将为其进行主要版本滚动。 当前客户端中可能存在一个错误,因此值得等待更改推出以查看它是否可以解决问题。

@ childish-sambino我要开一张票,谢谢! 如果最后与他们解决问题,我将在此处发布

_fwiw在此处添加我的评论,以防有人用其他关键词打它_

我们正在使用jest运行几个动态模板测试。 在整个上午没有问题地运行相同的测试套件之后,我们今天下午开始遇到同一随机401问题。 我将测试组减少到10个测试,并且我们以开玩笑的顺序运行它们(因此,不会同时发出多个send请求)。 在这10个测试中,可靠地,没有数量的测试并且没有任何一个测试会在后续运行中失败。 在一套10试验随机失败返回401相同,我们已经走了这么远,记录哪些客户端使用,当使用请求数据request内部-在Authorization头球为每个失败的请求更正。

考虑到客户端代码的简单性,这对我来说更像是网络问题或网络限制。

问题还没有解决; 我正在使用最新版本7,有时会得到:

未经授权(401)错误:未经授权
在ResponseError(node_modules/@sendgrid/helpers/classes/response-error.js:19:5)
在axios.then.catch.error(node_modules/@sendgrid/client/src/classes/client.js:105:29)
在process._tickCallback(内部/进程/next_tick.js:109:7)

代码:401,
消息:“未经授权”,
响应:
{标头:
{服务器:“ nginx”,
date:'Fri,24 Apr 2020 12:45:01 GMT',
'content-type':'application / json',
'content-length':'74',
连接:“关闭”,
'access-control-allow-origin':' https :
'access-control-allow-methods':'POST',
'access-control-allow-headers':'授权,内容类型,代表,x-sg-elas-acl',
'access-control-max-age':'600',
'x-no-cors-reason':' https ://sendgrid.com/docs/Classroom/Basics/API/cors.html'},
身体: '' } }

支持说:

PDT 3月24日,下午12:33
你好

感谢您的答复和其他见解。 我已就此问题向我们的团队查询。 事实证明,连续快速进行“邮件发送”呼叫可能会间歇性导致401错误。 造成不便之处,敬请原谅。 在这种情况下,建议您在收到401错误时在代码中实施某种形式的重试逻辑,以解决此问题。

希望这些信息对您有所帮助。 如果我无法回答您的问题,或者您还有其他问题或疑虑,请告诉我。

最好,
...

它什么时候可以解决?如果问题仍然存在,为什么问题还没有解决?

这也发生在我身上,但我认为我的问题有所不同。

因为我已经达到每天100封邮件的限制,所以没有别的。

批量电子邮件现在可以完美发送,没有任何错误。

idk,如果它只是想分享就可以。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

onesien picture onesien  ·  23评论

ifndefdeadmau5 picture ifndefdeadmau5  ·  33评论

machinshin picture machinshin  ·  35评论

adamreisnz picture adamreisnz  ·  25评论

mindnuts picture mindnuts  ·  41评论