使用Powershell使用Mailgun发送附件

时间:2017-08-02 14:16:04

标签: powershell email-attachments mailgun

我无法在Google或Mailgun支持上找到任何关于如何使用Powershell发送附件的答案。发送没有附件的邮件可以与Mailgun和Powershell一起使用。这是我的代码。

        $apikey = "key-1342323f7d35352fa4dda3af3ca10e"
        $idpass = "api:$($apikey)"
        $basicauth = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($idpass))
        $headers = @{
            Authorization = "Basic $basicauth";
        }
        $url = "https://api.mailgun.net/v3/sandboxac77741768d442323b96495501ac24b.mailgun.org/messages"
        $mailbody = @{
            from = "Mailgun Sandbox <postmaster@sandboxac77741768d442323b96495501ac24b.mailgun.org>";
            to = "myadress@email.com";
            subject = "Testing mail";
            text = "Email body here";
            attachment = "D:\temp\logfile.txt"          
        }
        Invoke-RestMethod -Uri $url -Method Post -Headers $headers -Body $mailbody -ContentType "multipart/form-data"

这会导致: Invoke-RestMethod:远程服务器返回错误:(400)错误请求

2 个答案:

答案 0 :(得分:1)

特别感谢我偷了代码的https://stackoverflow.com/users/213135/alex

function ConvertTo-MimeMultiPartBody {
    param([Parameter(Mandatory=$true)][string]$Boundary, [Parameter(Mandatory=$true)][hashtable]$Data)

    $body = "";
    $Data.GetEnumerator() |% {
        $name = $_.Key
        $value = $_.Value

        $body += "--$Boundary`r`n"
        $body += "Content-Disposition: form-data; name=`"$name`""
        if ($value -is [byte[]]) {
            $fileName = $Data['FileName']
            if(!$fileName) { $fileName = $name }
            $body += "; filename=`"$fileName`"`r`n"
            $body += 'Content-Type: application/octet-stream'
            $value = [System.Text.Encoding]::GetEncoding("ISO-8859-1").GetString($value)
        }
        $body += "`r`n`r`n" + $value + "`r`n"
    }
    return $body + "--$boundary--"
}

$emaildomain = "example.com"
$apikey = "key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
$url = "https://api.mailgun.net/v2/$($emaildomain)/messages"
$headers = @{
    Authorization = "Basic " + ([System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("api:$($apikey)")))
}

$email_parms = @{
    from = "me@example.com";
    to = "you@example.com";
    subject = "My Test Email";
    text = 'Your email does not support HTML.';
    html = "Hello World!";
    filename = "example.pdf"
    attachment = ([IO.File]::ReadAllBytes("c:\example.pdf"));
}
$boundary = [guid]::NewGuid().ToString()
$body = ConvertTo-MimeMultiPartBody $boundary $email_parms
Invoke-RestMethod -Uri $url -Method Post -Headers $headers -Body $body -ContentType "multipart/form-data; boundary=$boundary"

答案 1 :(得分:0)

要添加多个附件的轻微添加,请将其推入模块:

mailgun.psm1

<#
    .SYNOPSIS
        Interface to the Mailgun API Module

    .DESCRIPTION
        Sends an e-mail through the Mailgun API see https://documentation.mailgun.com/en/latest/user_manual.html#sending-via-api
        Define your maildomain and API key in MailGun.psd1 and place inside the module folder

    .EXAMPLE
        $from = "from@stackoverflow.com"
        $to = "to1@stackoverflow.com", "another@stackoverflow.com"
        $bcc = "bcc1@stackoveflow.com", "bcc2@stackoverflow.com"
        $subject = "a mail with a subject"
        $html = "this <b>test with attachments</b> text<br/> And another interesting line <hr />"
        $attachments = @{
            "ExampleAttachment1.png" = 'c:\temp\whatapps.png'
            "AnotherExample.txt" = 'c:\temp\Msinfo.txt'
        }
        Send-MailgunEmail -from $from -to -bcc $bcc $to -subject $subject -htmlText $html -attachments $attachments
#>
$ModuleData = Import-PowerShellDataFile "$PSScriptRoot\MailGun.psd1"

function ConvertTo-MimeMultiPartBody {
    <#
        .SYNOPSIS
            Convert email content with multiple attachments to correct format
            with help from https://stackoverflow.com/questions/45463391/sending-attachments-with-mailgun-using-powershell
    #>
    param(
        [Parameter(Mandatory = $true)]
        [string]
        $Boundary,

        [Parameter(Mandatory = $true)]
        [hashtable]
        $Data
    )

    $lb = "`r`n"
    $body = ""
    $Data.GetEnumerator() | ForEach-Object {
        $body += "--{0}{1}Content-Disposition: form-data; name=`"" -f $Boundary, $lb
        if ($_.Value -is [byte[]]) {
            $body += "attachment`"; filename=`"{0}`"{1}Content-Type: application/octet-stream{2}{3}{4}" -f
            $_.Key, $lb, $lb, $lb, [System.Text.Encoding]::GetEncoding("ISO-8859-1").GetString($_.Value)
        }
        else {
            $body += "{0}`"{1}{2}{3}" -f $_.Key, $lb, $lb, $_.Value
        }
        $body += $lb
    }
    return "{0}{1}--{2}--" -f $lb, $body, $boundary
}

function Send-MailgunEmail() {
    <#
        .SYNOPSIS
            Sends an email through mailguns API
    #>
    param(
        # The From e-mail address
        [Parameter(Mandatory = $True)]
        [string] $from,
        # The To e-mail address (comma divided string)
        [Parameter(Mandatory = $True)]
        [array] $to,
        # The bcc e-mail adresses
        [Parameter(Mandatory = $False)]
        [array] $bcc,
        # the subject
        [Parameter(Mandatory = $False)]
        [string] $subject = 'Mail without subject',
        # the text in the Text part
        [Parameter(Mandatory = $False)]
        [string] $text = 'Mail does not support Non Html readers',
        # the text in the HTML part
        [Parameter(Mandatory = $False)]
        [string] $htmlText = '<html>no body content</html>',
        # Either pass as parameter or set in MailGun.psd1
        [Parameter(Mandatory = $False)]
        [string] $emaildomain = $ModuleData.PrivateData.mailgun_emaildomain,
        # the api key as found in the mailgun profile either pass or set in MailGun.psd1
        [Parameter(Mandatory = $False)]
        [string] $apikey = $ModuleData.PrivateData.mailgun_apikey,
        # a list of attachments
        [Parameter(Mandatory = $False)]
        [hashtable] $attachments
    )

    $data = @{
        from    = $from
        to      = $to -join ','
        subject = $subject
        text    = $text
        html    = "<html>$htmlText</html>"
    }
    if ($bcc) { $data.Add('bcc', [string]($bcc -join ',')) }
    foreach ($attachment in $attachments.GetEnumerator()) {
        $attachmentbytes = [IO.File]::ReadAllBytes($attachment.Value)
        $data.Add($attachment.Name, $attachmentbytes)
    }

    $url = "https://api.mailgun.net/v3/$($emaildomain)/messages"
    $headers = @{Authorization = "Basic " + [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("api:$($apikey)"))}
    $boundary = [guid]::NewGuid().ToString()
    $contenttype = "multipart/form-data; boundary=$boundary"
    $body = ConvertTo-MimeMultiPartBody -Boundary $boundary -Data $data

    return Invoke-RestMethod -Method Post -Uri $url -Headers $headers -Body $body -ContentType $contenttype
}

Export-ModuleMember -Function Send-MailgunEmail

mailgun.psd1

@{
    RootModule = 'MailGun.psd1'
    ModuleVersion = '1.0.0.0'
    GUID = 'e0383493-22b2-4838-8095-67c865ae46de'
    Author = 'edelwater'

    PrivateData = @{
        mailgun_emaildomain = 'EXAMPLE.COM'
        mailgun_apikey = 'key-123fdsdafgd9gf043dfgd03sdd'
    }
}

testmailgunmodule.ps1

Import-Module "$PSScriptRoot\.\Modules\MailGun.psm1" -Force
$from = "from@stackoverflow.com"
        $to = "to1@stackoverflow.com", "another@stackoverflow.com"
        $bcc = "bcc1@stackoveflow.com", "bcc2@stackoverflow.com"
        $subject = "a mail with a subject"
        $html = "this <b>test with attachments</b> text<br/> And another interesting line <hr />"
        $attachments = @{
            "ExampleAttachment1.png" = 'c:\temp\whatapps.png'
            "AnotherExample.txt" = 'c:\temp\Msinfo.txt'
        }


Send-MailgunEmail -from $from -to $to -subject $subject -htmlText $html -attachments $attachments