Unable to Send email with attachment using azure communication service

Hi @kazurayam @katalonautomation @katalonautomation
I am trying to send email after my test suite execution in azure pipeline using azure communication services, but unable to attach the run time generated .html file. Though i am able to locate the file successfully but getting error “Mismatch: 1 standard attachments + 0 inline attachments does not equal 0 attachment types” . Please help.

Please refer Below script detail and error screenshot:

Script used in azure pipeline YAML:

  • task: Bash@3
    displayName: ‘Send Email Notification’
    condition: always()
    inputs:
    targetType: ‘inline’
    script: |
    export AZURE_COMMUNICATION_CONNECTION_STRING=“endpoint=;accesskey=”
    ls -l /d/a/1/a/allreports///////.html | tail -n 1
    # Get the latest generated HTML file
    REPORT_PATH=$(ls -t D:/a/1/a/allreports/
    //////.html | head -n 1)
    REPORT_NAME=$(basename “$REPORT_PATH”)

    if [[ -z "$REPORT_PATH" ]]; then
      echo "Error: No HTML report found."
      exit 1
    fi
    
    az communication email send \
      --connection-string "$AZURE_COMMUNICATION_CONNECTION_STRING" \
      --sender "noreply@xyz.com" \
      --to "nitin@xyz.com" \
      --subject "Pipeline Execution Status" \
      --text "The pipeline has completed successfully. Please find the report attached." \
      --attachments "[{\"name\": \"$REPORT_NAME\", \"path\": \"$REPORT_PATH\", \"contentType\": \"text/html\"}]"
    

Error:

1 Like

I know nothing about Azure.
Sorry I can not help you.

To resolve the attachment mismatch error when sending emails via Azure Communication Services in your pipeline, follow these steps:

1. Fix JSON Formatting for Attachments

Use single quotes to encapsulate the JSON array and ensure proper escaping:

az communication email send \
  --connection-string "$AZURE_COMMUNICATION_CONNECTION_STRING" \
  --sender "noreply@xyz.com" \
  --to "nitin@xyz.com" \
  --subject "Pipeline Execution Status" \
  --text "The pipeline has completed successfully. Please find the report attached." \
  --attachments '[{\"name\": \"'"$REPORT_NAME"'\", \"path\": \"'"$REPORT_PATH"'\", \"contentType\": \"text/html\"}]'

2. Verify File Paths

Use Absolute Paths Explicitly

# For Windows agents (use backslashes and escape them)
REPORT_PATH="D:\\a\\1\\a\\allreports\\\\\\.html"

# For Linux agents
REPORT_PATH="/d/a/1/a/allreports///////.html"

Check File Exists Before Sending

if [[ ! -f "$REPORT_PATH" ]]; then
  echo "Error: Report file not found at $REPORT_PATH"
  exit 1
fi

3. Simplify File Selection

Avoid ambiguity by using a precise filename pattern:

REPORT_PATH=$(find /d/a/1/a/allreports -name "*.html" -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" ")

4. Debugging Commands

Add verbose logging to inspect variables:

echo "Report Path: $REPORT_PATH"
echo "Report Name: $REPORT_NAME"
ls -l "$REPORT_PATH"

5. Full Corrected Script

- task: Bash@3
  displayName: 'Send Email Notification'
  condition: always()
  inputs:
    targetType: 'inline'
    script: |
      export AZURE_COMMUNICATION_CONNECTION_STRING="endpoint=;accesskey="
      
      # Get the latest HTML report
      REPORT_PATH=$(find /d/a/1/a/allreports -name "*.html" -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" ")
      if [[ -z "$REPORT_PATH" ]]; then
        echo "Error: No HTML report found."
        exit 1
      fi
      REPORT_NAME=$(basename "$REPORT_PATH")
      
      # Debugging
      echo "Report Path: $REPORT_PATH"
      echo "Report Name: $REPORT_NAME"
      ls -l "$REPORT_PATH"
      
      # Send email with attachment
      az communication email send \
        --connection-string "$AZURE_COMMUNICATION_CONNECTION_STRING" \
        --sender "noreply@xyz.com" \
        --to "nitin@xyz.com" \
        --subject "Pipeline Execution Status" \
        --text "The pipeline has completed successfully. Please find the report attached." \
        --attachments '[{\"name\": \"'"$REPORT_NAME"'\", \"path\": \"'"$REPORT_PATH"'\", \"contentType\": \"text/html\"}]'

Key Fixes

  • JSON Syntax: Escaped quotes and single quotes to preserve JSON structure.
  • Path Handling: Validated absolute paths and file existence.
  • Attachment MIME Type: Explicitly set text/html.

Common Issues

  • Incorrect Escaping: Missing backslashes (\") in JSON keys/values.
  • Variable Expansion: Unquoted variables causing spaces in paths to break JSON.
  • File Not Found: Relative paths in CI/CD environments differ from local.

Can you please tag anyone who can support here as i am struggling with this, I am executing test suites using Katalon with azure.

Hi @sureshyadav.devarala,

If you have a paid license from Katalon, you can reach out to our Support agent via this portal https://katalon-inc.my.site.com/support/.

This is a technical support community forum where our users are trying to connect and support other users as much as they can in their capacity. Hope this helps!

Thanks Dinesh for the detailed response.
I am using window based agent and when I give path with the ‘\’ (D:\a\1\a\allreports\\\\\\\.html) then it has not been identified but when gives path In other style D:/a/1/a/allreports///////.html then it is identifying the right html file.
But, again I am getting the same mismatch issue. Please find the attached error logs and my complete yaml file:

YAML:
trigger:

  • none

pool:
vmImage: ‘windows-latest’

variables:
Status: “”

steps:

  • task: katalonTask@1
    displayName: ‘LoyaltyPoint_Day1_DE’

    condition: always()

    inputs:
    version: ‘9.6.0’
    executeArgs: ‘-browserType=“Chrome (headless)” -retry=0 -statusDelay=15 -testSuitePath=“.\Test Suites” -apiKey= --config -proxy.auth.option=NO_PROXY -proxy.system.option=NO_PROXY -proxy.system.applyToDesiredCapabilities=true -webui.autoUpdateDrivers=true’

  • task: PublishBuildArtifacts@1
    displayName: Publish Artifact
    condition: always()
    inputs :
    PathtoPublish: ‘$(Build.SourcesDirectory)\Reports’
    # targetPath: ‘sunrisereport.html’
    ArtifactName: ‘allreports’
    publishLocation: ‘container’

  • task: DownloadBuildArtifacts@0
    displayName: DownloadBuildArtifacts
    condition: always()
    inputs:
    buildType: ‘current’
    downloadType: ‘single’
    artifactName: ‘allreports’
    downloadPath: ‘$(build.artifactstagingdirectory)’

  • powershell: |
    if (“$(Agent.JobStatus)” -eq “Succeeded”) {
    Write-Host “##vso[task.setvariable variable=Status][PASSED]”
    } else {
    Write-Host “##vso[task.setvariable variable=Status][FAILED]”
    }
    displayName: ‘Set Build Status’
    condition: always()

  • task: Bash@3
    displayName: ‘Send Email Notification’
    condition: always()
    inputs:
    targetType: ‘inline’
    script: |
    export AZURE_COMMUNICATION_CONNECTION_STRING=“endpoint=;accesskey=”

    # Get the latest HTML report
    REPORT_PATH=$(find D:/a/1/a/allreports/*/*/*/*/*/*/*.html -name "*.html" -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" ")
    if [[ -z "$REPORT_PATH" ]]; then
      echo "Error: No HTML report found."
      exit 1
    fi
    REPORT_NAME=$(basename "$REPORT_PATH")
    
    # Debugging
    echo "Report Path: $REPORT_PATH"
    echo "Report Name: $REPORT_NAME"
    ls -l "$REPORT_PATH"
    
    # Send email with attachment
    az communication email send \
      --connection-string "$AZURE_COMMUNICATION_CONNECTION_STRING" \
      --sender "noreply@info.com" \
      --to "nitin.sharma6@info.com" \
      --subject "Pipeline Execution Status" \
      --text "The pipeline has completed successfully. Please find the report attached." \
      --attachments '[{\"name\": \"'"$REPORT_NAME"'\", \"path\": \"'"$REPORT_PATH"'\", \"contentType\": \"text/html\"}]'
    

@sureshyadav.devarala

Please use the “code formatting” syntax to make the code snippets in your posts readable.

Why do I say this? — Your post does not make sense unless formatted properly.

For example, in the previous post you wrote:

The path expression “D:\a...” here does not make sense to me at all. Therefore I replied “I don’t know Azure” in a previous post. I really didn’t understand your posts.

But I found in the raw code of your post, you wanted to write

D:\a\1\a\allreports\*\*\*\*\*\*\*.html

This path expression is completely different from what you actually presented in the previous posts. Your previous posts confuse us — the guys who visited this forum.

Backslash character \ confuses everyone in many places (yaml, json, markdown).

But a savior comes, as you noticed:

This finding suggests that Azure will accept forward slash chacater / instead of \ as file separator character.

I would recommend you to avoid backslash characters completely. You should use / instead in the pipeline definition yaml file. Things will become much easier.

Backslash character \ on Windows confuses everyone in many places (yaml, json, markdown).

Let me quote an interesting read here:

  • ** recursive wildcard. For example, /hello/**/* matches all descendants of /hello.

Therefore you can rewrite

D:/a/1/a/allreports/*/*/*/*/*/*/*.html

to

D:/a/1/a/allreports/**/*.html

Much simpler, isn’t it?

@dineshh @kazurayam

Yes I am using / in the path which is identifying my file correctly but again getting the mismatch issue

r u saying to change \ with / only in Report_Path or everywhere in below script also:

 # Send email with attachment
  az communication email send \
    --connection-string "$AZURE_COMMUNICATION_CONNECTION_STRING" \
    --sender "noreply@info.com" \
    --to "nitin.sharma6@info.com" \
    --subject "Pipeline Execution Status" \
    --text "The pipeline has completed successfully. Please find the report attached." \
    --attachments '[{\"name\": \"'"$REPORT_NAME"'\", \"path\": \"'"$REPORT_PATH"'\", \"contentType\": \"text/html\"}]'

Yes it is simpler thanks for suggesting but my file is correctly identified if you see the log error which i attached earlier, main issue is Mismatching of file during attachment. Tried many solutions but nothing works.

I have no more idea.

to resolve the attachment mismatch error in your Azure Pipeline when sending emails via Azure Communication Services:

1. Fix JSON Formatting for Attachments

Use a here-document to avoid complex escaping and ensure valid JSON:

task: Bash@3
displayName: 'Send Email Notification'
condition: always()
inputs:
  targetType: 'inline'
  script: |
    export AZURE_COMMUNICATION_CONNECTION_STRING="endpoint=;accesskey="
    
    # Get the latest HTML report (Windows-style path with forward slashes)
    REPORT_PATH="D:/a/1/a/allreports/Test Suites/Reports/$(ls -t D:/a/1/a/allreports/Test\ Suites/Reports | grep '.html' | head -1)"
    REPORT_NAME=$(basename "$REPORT_PATH")
    
    # Validate file exists
    if [[ ! -f "$REPORT_PATH" ]]; then
      echo "Error: Report file not found at $REPORT_PATH"
      exit 1
    fi
    
    # Debugging
    echo "Report Path: $REPORT_PATH"
    echo "Report Name: $REPORT_NAME"
    ls -l "$REPORT_PATH"
    
    # Send email with attachment using here-document
    az communication email send \
      --connection-string "$AZURE_COMMUNICATION_CONNECTION_STRING" \
      --sender "noreply@info.com" \
      --to "nitin.sharma6@info.com" \
      --subject "Pipeline Execution Status" \
      --text "The pipeline has completed. Report attached." \
      --attachments @- <<EOF
    [
      {
        "name": "$REPORT_NAME",
        "path": "$REPORT_PATH",
        "contentType": "text/html"
      }
    ]
    EOF

2. Key Fixes Applied

  • Simplified File Path:
    • Avoid find complexity with explicit path:
REPORT_PATH="D:/a/1/a/allreports/Test Suites/Reports/$(ls -t D:/a/1/a/allreports/Test\ Suites/Reports | grep '.html' | head -1)"
  • Uses forward slashes (works on Windows agents).
  • Valid JSON via Here-Document:
    • Eliminates quote escaping issues.
    • Uses @- to read JSON from stdin.

3. Pipeline Adjustments

  1. Ensure File Exists in Correct Location:
  • Confirm PublishBuildArtifacts@1 publishes reports to D:\a\1\a\allreports.
  1. Upgrade Azure CLI:
    Add a step to use the latest CLI version:
- task: AzureCLI@2
  displayName: "Install Latest Azure CLI"
  inputs:
    azureSubscription: ""
    scriptType: "ps"
    scriptLocation: "inlineScript"
    inlineScript: |
      az upgrade --yes

4. Verify Permissions

  • The Azure Pipeline service account must have read access to the report directory.
  • Use icacls to check permissions in a PowerShell step:
- powershell: |
    icacls "D:\a\1\a\allreports"
  displayName: "Check File Permissions"

5. Alternative: Use PowerShell Instead of Bash

Better handling of Windows paths and JSON:

- task: PowerShell@2
  displayName: "Send Email (PowerShell)"
  condition: always()
  inputs:
    targetType: 'inline'
    script: |
      $env:AZURE_COMMUNICATION_CONNECTION_STRING = "endpoint=;accesskey="
      
      # Get latest report
      $reportDir = "D:\a\1\a\allreports\Test Suites\Reports"
      $report = Get-ChildItem -Path $reportDir -Filter *.html | Sort-Object LastWriteTime | Select-Object -Last 1
      if (-not $report) { throw "No report found" }
      
      # Send email
      az communication email send `
        --connection-string $env:AZURE_COMMUNICATION_CONNECTION_STRING `
        --sender "noreply@info.com" `
        --to "nitin.sharma6@info.com" `
        --subject "Pipeline Status" `
        --text "Report attached." `
        --attachments "[{ \`"name\`": \`"$($report.Name)\`", \`"path\`": \`"$($report.FullName)\`", \`"contentType\`": \`"text/html\`" }]"

Why This Happened

  • JSON Escaping Issues: Mixing quotes in Bash led to malformed JSON.
  • Path Case Sensitivity: Forward slashes work, but inconsistent paths caused confusion.
  • File Timing: Reports might not be fully written before email task runs.