使用gapi打字稿发送电子邮件在已发送框中显示错误编码的电子邮件

问题描述

我使用 gapi 发送电子邮件。接收器正确接收它们,但是当我开始查看“已发送”框时,它们看起来就像是中文乱码。喜欢this image

更具体地说,只有当我使用非 Gmail 应用程序时,它才会看起来像这样。因此,如果我在 Gmail 中查看我的“已发送”框,它看起来不错,但是如果我使用 Outlook 或如果我使用我的 Android 的邮件应用程序并将其与我的 gmail 帐户连接并查看“已发送”文件夹,它就完全搞砸了。显然它与编码有关,但显然 gmail 设法修复它而其他应用程序没有。

这是我用来发送电子邮件代码

async sendMail(email,files) {
    //create cc and bcc string if needed
    let ccStr = `Cc: ${email.cc}\r\n`
    let bccStr = `Bcc: ${email.bcc}\r\n`

    //create attachment if needed
    let attachStr = await this.createAttachmentStr(files)
    attachStr = `${attachStr}\r\n\r\n`

    //create the message
    let message = 'Content-Type: multipart/mixed; boundary="#split-part#"\r\n' +
      'MIME-Version: 1.0\r\n' +
      `To: ${email.to}\r\n` +
      `From: ${email.from}\r\n` +
      ccStr +
      bccStr +
      `Subject: ${email.subject}\r\n\r\n` +
      '--#split-part#\r\n' +
      'Content-Type: text/html; charset="UTF-8"\r\n' +
      'MIME-Version: 1.0\r\n' +
      'Content-transfer-encoding: base64\r\n\r\n' +
      `${email.message}\r\n\r\n` +
      `${attachStr}` +
      '--#split-part#--'

    //base64url encode
    const encodedMessage = btoa(unescape(encodeURIComponent(message))).replace(/\+/g,'-').replace(/\//g,'_').replace(/=+$/,'')

    //send to api
    gapi.client["gmail"].users.messages.send({
      'userId': 'me','resource': {
        'raw': encodedMessage,"payload": {
          "mimeType": 'multipart/mixed'
        },'threadId': email.id
      }
    }).then(async response => {
      //do some stuff after
    })
  }

那里使用的方法称为基于 FileList 的 createAttachmentStr:

createAttachmentStr(files: FileList): Promise<string> {
    return new Promise<string>((resolve) => {
      let attachStr = ""

      //initialize counter
      let count = 0

      //loop through each file
      if (files && files.length > 0) {
        Array.from(files).forEach(async file => {
          //convert file to datastrings
          let dataStr = await this.readFileContent(file)

          //get file info
          let fileName = file.name
          let contentType = file.type

          //create message str
          attachStr += '--#split-part#\r\n' +
            `Content-Type: ${contentType}\r\n` +
            'MIME-Version: 1.0\r\n' +
            'Content-transfer-encoding: base64\r\n' +
            `Content-disposition: attachment; filename="${fileName}"\r\n\r\n` +
            `${dataStr}\r\n\r\n`

          //increase the counter
          count++

          if (count === files.length) {
            resolve(attachStr);
          }
        });
      }
      else resolve("")
    });
  }

请注意,这并不总是发生,实际上很少发生,但我无法弄清楚究竟是什么触发了它。似乎与一些带有特定附件的电子邮件有关。

我对这个有点迷茫,所以感谢任何帮助

解决方法

既然你提到它似乎与特定的附件有关,则表明问题与电子邮件的内容类型标题有关:

Content-Type: text/html; charset="UTF-8"

意思是其中一个(或两者):

  1. 您的某些附件(可能还有 email.message)不是 HTML 文件(这也意味着不应将邮件的这些部分传递给 encodeURIComponent)。

  2. dataStr 不是 utf-8 编码的,这意味着 this.readFileContent(file) 将文件读取为 utf-8 编码的文件,而它实际上有一些其他编码。

另一种选择是某些附件文件的 contentType 构造了一个错误的附件头(即,它与实际文件类型不对应),部分(例如,缺少 charset="UTF-8" 部分) ) 或无效(即不存在的内容类型),在以下行中:

`Content-Type: ${contentType}\r\n`