首页 > 解决方案 > 使用 Axios 在 Microsoft Teams 中发布消息

问题描述

更新的问题 2020 年 16 月 10 日 我简化了代码,因此它不再包含 if 语句来运行 postMessageToTeams 函数,并且我添加了我在 catch 中收到的错误响应。希望这使调试更容易。

当我从我的 Visual Studio 终端运行脚本时它可以工作,但从我的cmder 运行它时它不起作用。所以我认为这与我的cmder设置有关。

目标

我正在通过 testcafe 运行一些自动化任务,并希望在完成特定任务时在 Microsoft Teams 中收到通知。为此,我在我的频道中创建了一个 webhook,并希望向我的 webhook URL 发送一个 POST 请求。但是,这样做时,我收到 405 错误。在 Postman 中试用时,它确实可以使用相同的 JSON 数据。

我的代码(我稍微更改了https://gist.github.com/johnsibly/806a7190fbdc4b439ed040f327e6e679中的代码以进行此测试)

const axios = require('axios'); // axios must be installed via npm i axios
const webhookURL = "https://outlook.office.com/webhook/xxxxx"; // this holds my webhook URL

postMessageToTeams();

async function postMessageToTeams(title, message) {
    const card = {
      "@type": "MessageCard",
      "@context": "http://schema.org/extensions",
      "themeColor": "0072C6",
      "summary": "Summary description",
      "sections": [
        {
          "activityTitle": "Testcafe",
          "text": "Testcafe is talking to you"
        }
      ]
    };

    try {
      const response = await axios.post(webhookURL, card, {
        headers: {
          'content-type': 'application/vnd.microsoft.teams.card.o365connector',
          'content-length': `${card.toString().length}`,
        },
      });
      return `${response.status} - ${response.statusText}`;
    } catch (err) {
        console.log(err)
      return err;
    }
  }

错误响应

{
  status: 405,
  statusText: 'Method Not Allowed',
  headers: {
    'cache-control': 'no-cache',
    pragma: 'no-cache',
    allow: 'POST',
    'content-length': '43',
    'content-type': 'text/plain; charset=utf-8',
    expires: '-1',
    server: 'Microsoft-IIS/10.0',
    'request-id': 'b565e1ec-79a2-4fc1-99e1-56e8caa98a48',
    'strict-transport-security': 'max-age=31536000; includeSubDomains; preload',
    'x-calculatedbetarget': 'AM0PR02MB5570.eurprd02.prod.outlook.com',
    'x-backendhttpstatus': '405',
    'x-aspnet-version': '4.0.30319',
    'x-cafeserver': 'AM3PR07CA0145.EURPRD07.PROD.OUTLOOK.COM',
    'x-beserver': 'AM0PR02MB5570',
    'x-proxy-routingcorrectness': '1',
    'x-proxy-backendserverstatus': '405',
    'x-powered-by': 'ASP.NET',
    'x-feserver': 'AM3PR07CA0145',
    date: 'Fri, 16 Oct 2020 07:58:34 GMT',
    connection: 'close'
  },
  config: {
    url: 'https://outlook.office.com/webhook/xxxx',
    method: 'post',
    data: '{"@type":"MessageCard","@context":"http://schema.org/extensions","themeColor":"0072C6","summary":"Summary description","sections":[{"activityTitle":"Testcafe","text":"Testcafe is talking to you"}]}',
    headers: {
      Accept: 'application/json, text/plain, */*',
      'User-Agent': 'axios/0.20.0'
    },
    transformRequest: [ [Function: transformRequest] ],
    transformResponse: [ [Function: transformResponse] ],
    timeout: 0,
    adapter: [Function: httpAdapter],
    xsrfCookieName: 'XSRF-TOKEN',
    xsrfHeaderName: 'X-XSRF-TOKEN',
    maxContentLength: -1,
    maxBodyLength: -1,
    validateStatus: [Function: validateStatus]
  },
  request: <ref *1> ClientRequest {
    _events: [Object: null prototype] {
      socket: [Function (anonymous)],
      abort: [Function (anonymous)],
      aborted: [Function (anonymous)],
      connect: [Function (anonymous)],
      error: [Function (anonymous)],
      timeout: [Function (anonymous)],
      prefinish: [Function: requestOnPrefinish]
    },
    _eventsCount: 7,
    _maxListeners: undefined,
    outputData: [],
    outputSize: 0,
    writable: true,
    _last: true,
    chunkedEncoding: false,
    shouldKeepAlive: false,
    useChunkedEncodingByDefault: false,
    sendDate: false,
    _removedConnection: false,
    _removedContLen: false,
    _removedTE: false,
    _contentLength: 0,
    _hasBody: true,
    _trailer: '',
    finished: true,
    _headerSent: true,
    socket: TLSSocket {
      _tlsOptions: [Object],
      _secureEstablished: true,
      _securePending: false,
      _newSessionPending: false,
      _controlReleased: true,
      _SNICallback: null,
      servername: 'outlook.office.com',
      alpnProtocol: false,
      authorized: true,
      authorizationError: null,
      encrypted: true,
      _events: [Object: null prototype],
      _eventsCount: 9,
      connecting: false,
      _hadError: false,
      _parent: null,
      _host: 'outlook.office.com',
      _readableState: [ReadableState],
      readable: true,
      _maxListeners: undefined,
      _writableState: [WritableState],
      writable: false,
      allowHalfOpen: false,
      _sockname: null,
      _pendingData: null,
      _pendingEncoding: '',
      server: undefined,
      _server: null,
      ssl: [TLSWrap],
      _requestCert: true,
      _rejectUnauthorized: true,
      parser: null,
      _httpMessage: [Circular *1],
      [Symbol(res)]: [TLSWrap],
      [Symbol(asyncId)]: 15,
      [Symbol(kHandle)]: [TLSWrap],
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: null,
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kBytesRead)]: 0,
      [Symbol(kBytesWritten)]: 0,
      [Symbol(connect-options)]: [Object]
    },
    _header: 'GET /webhook/xxxx HTTP/1.1\r\n' +
      'Accept: application/json, text/plain, */*\r\n' +
      'User-Agent: axios/0.20.0\r\n' +
      'Host: outlook.office.com\r\n' +
      'Connection: close\r\n' +
      '\r\n',
    _onPendingData: [Function: noopPendingOutput],
    agent: Agent {
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      defaultPort: 443,
      protocol: 'https:',
      options: [Object],
      requests: {},
      sockets: [Object],
      freeSockets: {},
      keepAliveMsecs: 1000,
      keepAlive: false,
      maxSockets: Infinity,
      maxFreeSockets: 256,
      maxCachedSessions: 100,
      _sessionCache: [Object],
      [Symbol(kCapture)]: false
    },
    socketPath: undefined,
    method: 'GET',
    maxHeaderSize: undefined,
    path: '/webhook/xxxx',
    _ended: true,
    res: IncomingMessage {
      _readableState: [ReadableState],
      readable: false,
      _events: [Object: null prototype],
      _eventsCount: 3,
      _maxListeners: undefined,
      socket: [TLSSocket],
      httpVersionMajor: 1,
      httpVersionMinor: 1,
      httpVersion: '1.1',
      complete: true,
      headers: [Object],
      rawHeaders: [Array],
      trailers: {},
      rawTrailers: [],
      aborted: false,
      upgrade: false,
      url: '',
      method: null,
      statusCode: 405,
      statusMessage: 'Method Not Allowed',
      client: [TLSSocket],
      _consuming: false,
      _dumped: false,
      req: [Circular *1],
      responseUrl: 'https://outlook.office.com/webhook/xxxx',
      redirects: [],
      [Symbol(kCapture)]: false
    },
    aborted: false,
    timeoutCb: null,
    upgradeOrConnect: false,
    parser: null,
    maxHeadersCount: null,
    reusedSocket: false,
    _redirectable: Writable {
      _writableState: [WritableState],
      writable: true,
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      _options: [Object],
      _ended: true,
      _ending: true,
      _redirectCount: 1,
      _redirects: [],
      _requestBodyLength: 197,
      _requestBodyBuffers: [],
      _onNativeResponse: [Function (anonymous)],
      _currentRequest: [Circular *1],
      _currentUrl: 'https://outlook.office.com/webhook/xxxx',
      _isRedirect: true,
      [Symbol(kCapture)]: false
    },
    [Symbol(kCapture)]: false,
    [Symbol(kNeedDrain)]: false,
    [Symbol(corked)]: 0,
    [Symbol(kOutHeaders)]: [Object: null prototype] {
      accept: [Array],
      'user-agent': [Array],
      host: [Array]
    }
  },
  data: 'Invalid webhook request - GET not supported'
}

如果您需要完整的错误消息才能正确调试,请告诉我。

邮差

POST 请求的正文(原始)

{
  "@type": "MessageCard",
  "@context": "http://schema.org/extensions",
  "themeColor": "0072C6",
  "summary": "Summary description",
  "sections": [
    {
      "activityTitle": "Testcafe",
      "text": "Testcafe is talking to you"
    }
  ]
}

回复

1,并且消息发布在我的团队频道中

标签: javascriptaxiospostmanmicrosoft-teams

解决方案


您应该让axios处理有效载荷长度的计算,因此删除此行:

'content-length': `${card.toString().length}`

您的帖子生成的脚本如下所示:

const axios = require('axios'); // axios must be installed via npm i axios
const webhookURL = "https://outlook.office.com/webhook/xxxxx"; // this holds my webhook URL

postMessageToTeams();

async function postMessageToTeams(title, message) {
    const card = {
      "@type": "MessageCard",
      "@context": "http://schema.org/extensions",
      "themeColor": "0072C6",
      "summary": "Summary description",
      "sections": [
        {
          "activityTitle": "Testcafe",
          "text": "Testcafe is talking to you"
        }
      ]
    };

    try {
      const response = await axios.post(webhookURL, card, {
        headers: {
          'content-type': 'application/vnd.microsoft.teams.card.o365connector'
        },
      });
      return `${response.status} - ${response.statusText}`;
    } catch (err) {
        console.log(err)
      return err;
    }
  }

发现这对我有用。


推荐阅读