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

GitLab Pipeline通过SendGrid发送附件时遇Bad Request错误求解决

问题:GitLab Pipeline使用SendGrid发送带base64附件时返回Bad Request错误

在GitLab Pipeline中配置SendGrid发送邮件通知,发送空附件时一切正常,但附加转换为base64格式的checkov报告时,出现Bad Request错误。以下是当前的Pipeline配置:

send_email:
  image: alpine
  stage: send_email
  before_script:
    - apk add curl file
  script:
    - SENDGRID_ATTACHMENT_FILE_PATH="reports/checkov.txt"
    - SENDGRID_ATTACHMENT_FILENAME=$(basename $SENDGRID_ATTACHMENT_FILE_PATH)
    - SENDGRID_ATTACHMENT_BASE64_CONTENT=$(base64 -i $SENDGRID_ATTACHMENT_FILE_PATH)
    - SENDGRID_ATTACHMENT_FILETYPE=$(file -b --mime-type $SENDGRID_ATTACHMENT_FILE_PATH)
    - echo $SENDGRID_ATTACHMENT_FILENAME
    - echo $SENDGRID_ATTACHMENT_FILETYPE
    - echo $SENDGRID_ATTACHMENT_BASE64_CONTENT
    - |
      curl --request POST \
      --url https://api.sendgrid.com/v3/mail/send \
      --header "Authorization: Bearer YOUR_SENDGRID_API_KEY" \
      --header "Content-Type: application/json" \
      --data "{
        \"personalizations\": [{\"to\": [{\"email\": \"RECIPIENT_EMAIL\"}], \"subject\": \"Your job report is here!\"}],
        \"content\": [{\"type\": \"text/plain\", \"value\": \"See the attached job report.\"}],
        \"from\": {\"email\": \"SENDER_EMAIL\", \"name\": \"Your GitLab\"},
        \"attachments\": [{
          \"content\": \"$SENDGRID_ATTACHMENT_BASE64_CONTENT\",
          \"type\": \"$SENDGRID_ATTACHMENT_FILETYPE\",
          \"filename\": \"$SENDGRID_ATTACHMENT_FILENAME\"
        }]
      }"
解决办法

核心问题分析

Bad Request错误主要来自两个方面:base64内容格式不符合SendGrid要求,或者手动构建的JSON存在格式问题。

1. 移除base64内容中的换行符

Alpine系统的base64命令默认会每76个字符添加换行符,而SendGrid要求附件的base64内容是无换行的单行字符串,换行符会导致JSON解析失败。

修改base64命令,添加-w 0参数禁用换行:

SENDGRID_ATTACHMENT_BASE64_CONTENT=$(base64 -i -w 0 $SENDGRID_ATTACHMENT_FILE_PATH)

2. 使用jq构建JSON避免转义问题

手动拼接JSON字符串时,若base64内容包含特殊字符(如引号),会直接破坏JSON结构。建议用jq工具来生成合法的JSON,无需手动转义。

步骤:

  • 在before_script中安装jq:
    apk add curl file jq
    
  • 修改script中的curl部分,用jq构建请求体:
    - |
      curl --request POST \
      --url https://api.sendgrid.com/v3/mail/send \
      --header "Authorization: Bearer YOUR_SENDGRID_API_KEY" \
      --header "Content-Type: application/json" \
      --data "$(jq -n \
        --arg to "RECIPIENT_EMAIL" \
        --arg subject "Your job report is here!" \
        --arg from_email "SENDER_EMAIL" \
        --arg from_name "Your GitLab" \
        --arg content "See the attached job report." \
        --arg attach_content "$SENDGRID_ATTACHMENT_BASE64_CONTENT" \
        --arg attach_type "$SENDGRID_ATTACHMENT_FILETYPE" \
        --arg attach_name "$SENDGRID_ATTACHMENT_FILENAME" \
        '{
          personalizations: [{to: [{email: $to}], subject: $subject}],
          content: [{type: "text/plain", value: $content}],
          from: {email: $from_email, name: $from_name},
          attachments: [{
            content: $attach_content,
            type: $attach_type,
            filename: $attach_name
          }]
        }')"
    

3. 验证MIME类型(可选)

如果file命令返回的MIME类型异常(比如不是text/plain),可以手动指定类型,避免SendGrid识别错误:

SENDGRID_ATTACHMENT_FILETYPE="text/plain"

修改后的完整Pipeline配置

send_email:
  image: alpine
  stage: send_email
  before_script:
    - apk add curl file jq
  script:
    - SENDGRID_ATTACHMENT_FILE_PATH="reports/checkov.txt"
    - SENDGRID_ATTACHMENT_FILENAME=$(basename $SENDGRID_ATTACHMENT_FILE_PATH)
    - SENDGRID_ATTACHMENT_BASE64_CONTENT=$(base64 -i -w 0 $SENDGRID_ATTACHMENT_FILE_PATH)
    - SENDGRID_ATTACHMENT_FILETYPE=$(file -b --mime-type $SENDGRID_ATTACHMENT_FILE_PATH)
    - echo $SENDGRID_ATTACHMENT_FILENAME
    - echo $SENDGRID_ATTACHMENT_FILETYPE
    - echo $SENDGRID_ATTACHMENT_BASE64_CONTENT
    - |
      curl --request POST \
      --url https://api.sendgrid.com/v3/mail/send \
      --header "Authorization: Bearer YOUR_SENDGRID_API_KEY" \
      --header "Content-Type: application/json" \
      --data "$(jq -n \
        --arg to "RECIPIENT_EMAIL" \
        --arg subject "Your job report is here!" \
        --arg from_email "SENDER_EMAIL" \
        --arg from_name "Your GitLab" \
        --arg content "See the attached job report." \
        --arg attach_content "$SENDGRID_ATTACHMENT_BASE64_CONTENT" \
        --arg attach_type "$SENDGRID_ATTACHMENT_FILETYPE" \
        --arg attach_name "$SENDGRID_ATTACHMENT_FILENAME" \
        '{
          personalizations: [{to: [{email: $to}], subject: $subject}],
          content: [{type: "text/plain", value: $content}],
          from: {email: $from_email, name: $from_name},
          attachments: [{
            content: $attach_content,
            type: $attach_type,
            filename: $attach_name
          }]
        }')"

内容的提问来源于stack exchange,提问作者Shubham Aswal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 10:05:39