Powershell: Использование SendGrid для отправки почты с вложением

#excel #powershell #sendgrid #attachment

Вопрос:

Я пытаюсь отправлять электронные письма с вложениями Excel, как noreply@domain.com. Отправка работает, но проблема в вложении.

Вот как выглядит сценарий. Это работает в том смысле, что он получает отправку, но вложение повреждается. До этого я использовал метод outlook.application, который отлично работает. Единственная проблема в том, что я хочу скрыть свою электронную почту, чтобы мне не отвечали. Но я не могу этого сделать там, поэтому я использую sendgrid.

EDIT1: получил исходный код скелета из https://github.com/tsrob50/SendGridFunction/blob/master/SendGridFunction.ps1 Материал для прикрепления пришел от u/Pandapokeman, отправившего меня сюда: https://dzone.com/articles/how-to-send-an-email-with-attachement-powershell-sendgrid-api

 function Send-SendGridEmail {
  param(
    [Parameter(Mandatory = $true)]
    [String] $destEmailAddress,
    [Parameter(Mandatory = $true)]
    [String] $fromEmailAddress,
    [Parameter(Mandatory = $true)]
    [String] $subject,
    [Parameter(Mandatory = $false)]
    [string]$contentType = 'text/plain',
    [Parameter(Mandatory = $true)]
    [String] $contentBody,

    #Added after edit1
    [parameter(Mandatory = $false)]
    [string]$FileName,
    [parameter(Mandatory = $false)]
    [string]$FileNameWithFilePath,
    [parameter(Mandatory = $false)]
    [string]$AttachementType
  )

  <#
.Synopsis
Function to send email with SendGrid
.Description
A function to send a text or HTML based email
See https://sendgrid.com/docs/API_Reference/api_v3.html for API details
This script provided as-is with no warranty. Test it before you trust it.
www.ciraltos.com
.Parameter apiKey
The SendGrid API key associated with your account
.Parameter destEmailAddress
The destination email address
.Parameter fromEmailAddress
The from email address
.Parameter subject
Email subject
.Parameter type
The content type, values are “text/plain” or “text/html”.  "text/plain" set by default
.Parameter content
The content that you'd like to send
.Example
Send-SendGridEmail
#>
  ############ Update with your SendGrid API Key ####################
  $apiKey = "myKey"

  $headers = @{
    'Authorization' = 'Bearer '   $apiKey
    'Content-Type'  = 'application/json'
  }
  #Convert File to Base64
  $FileContent = get-content $FileNameWithFilePath
  $ConvertToBytes = [System.Text.Encoding]::UTF8.GetBytes($FileContent)
  $EncodedFile = [System.Convert]::ToBase64String($ConvertToBytes)

  $body = @{
    personalizations = @(
      @{
        to = @(
          @{
            email = $destEmailAddress
          }
        )
      }
    )
    from             = @{
      email = $fromEmailAddress
    }
    subject          = $subject
    content          = @(
      @{
        type  = $contentType
        value = $contentBody
      }
    )
    attachments = @(
        @{
            content=$EncodedFile
            filename=$FileName
            type= $AttachementType
            disposition="attachment"
        }
    )
  }

  try {
    $bodyJson = $body | ConvertTo-Json -Depth 4
  }
  catch {
    $ErrorMessage = $_.Exception.message
    write-error ('Error converting body to json '   $ErrorMessage)
    Break
  }

  try {
    Invoke-RestMethod -Uri https://api.sendgrid.com/v3/mail/send -Method Post -Headers $headers -Body $bodyJson 
  }
  catch {
    $ErrorMessage = $_.Exception.message
    write-error ('Error with Invoke-RestMethod '   $ErrorMessage)
    Break
  }

}
$htmlBody = @"
//STUFF
"@
$splat2 = @{
  destEmailAddress = 'dest'
  fromEmailAddress = 'noreply@domain.com'
  subject          = 'Test Email'
  contentType      = 'text/html'
  contentBody      = $htmlBody
  FileName         = "name.xlsx"
  FileNameWithFilePath = "path/name.xlsx"
  AttachementType ="text/xlsx"
}
 

Кто-то из reddit предложил использовать:
«Пример кода, на который вы ссылаетесь, использует html-файлы в качестве примера, но вы отправляете двоичные файлы. Вы захотите получить байты файла, используя вместо этого байт кодирования Get-Содержимого, иначе у вас могут возникнуть проблемы с последовательностями новых строк, которые могут быть испорчены из-за поведения Get-Содержимого по умолчанию».

Для чего я заменил:

 $FileContent = get-content $FileNameWithFilePath
with: $FileContent = Get-Content -Encoding Byte $FileNameWithFilePath
 

Что тоже не сработало.

ПРАВКА2: Пробовал:

 AttachementType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
 

Все еще испорчен

Ответ №1:

Этот единственный лайнер — то, что исправляет это для меня. Файл приходит в неповрежденном виде. Вместе с HAL9256 дал мне.

 $base64string = [Convert]::ToBase64String([IO.File]::ReadAllBytes($FileNameWithFilePath))
AttachmentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
 

Ни в одной другой кодировке нет. все это удалено/закомментировано