2021-10-17

PowerShellでJISコードのメールを送信する (MailKit編) (2)

前回のMimeKit導入編に続き、今回は実装編です。

以下のサイトを参考にPowerShellでJISコード(ISO-2022-JP)でメールを送信するコードを書いてみます。

電子メールを送信するには?(MailKit編)[.NET 4.5、C#/VB]:.NET TIPS - @IT

これまで広く使われてきたSmtpClientクラスは現在、使用が推奨されていない。そこでオープンソースライブラリのMailKitでメールを送信する方法を説明する。


  • 一般的なメールソフトと同様、宛先、CC、件名、本文、添付ファイルを引数にした関数にしています。
  • 宛先、CC、添付ファイルについては複数項目を受け付けるため配列を引数にしています。簡略化のため、宛先とCCの Display Name はなしにしています。
function Send-JisMail {
    param (
        [string[]]$ToArray,
        [string[]]$CcArray,
        [string]$Subject,
        [string]$Body,
        [string[]]$FileArray
    ) 
    # If you don't want to use arrays as arguments
    # $ToArray = $To.Replace(" ","").Split(",")
    Add-Type -Path "C:\Program Files\PackageManagement\NuGet\Packages\Portable.BouncyCastle.1.8.10\lib\net40\BouncyCastle.Crypto.dll"
    Add-Type -Path "C:\Program Files\PackageManagement\NuGet\Packages\MimeKit.2.15.1\lib\net45\MimeKit.dll"
    Add-Type -Path "C:\Program Files\PackageManagement\NuGet\Packages\MailKit.2.15.0\lib\net45\MailKit.dll"

    $fromAddress = "sender@foo.com"
    $fromName = $null
    # 送信サーバ設定
    $smtpServer = "smtp@foo.com"
    $port = "587"
    $user = "user"
    $password = "password"

    $message = New-Object Mimekit.MimeMessage
    $jis = [Text.Encoding]::GetEncoding("iso-2022-jp")
    $from = New-Object MimeKit.MailboxAddress($jis, $fromName, $fromAddress)
    $message.From.Add($from)
    #$ToArray = $toAddress.Replace(" ","").Split(",")
    foreach ($to in $ToArray) {
        $message.To.Add($to)
    }
    $message.Subject = $Subject
    $textPart = New-Object MimeKit.TextPart([MimeKit.Text.TextFormat]::Plain)
    $textPart.SetText($jis, $Body)

    #添付ファイル設定
    if ($FileArray) {
        $multiPart = New-Object MimeKit.Multipart("mixed")
        $multiPart.Add($textPart)
        foreach ($file in $FileArray) {
            $attachment = New-Object MimeKit.MimePart
            $content = New-Object MimeKit.MimeContent([System.IO.File]::OpenRead($file), [MimeKit.ContentEncoding]::Default)
            $attachment.Content = $content
            $contentDisposition = New-Object MimeKit.ContentDisposition([MimeKit.ContentDisposition]::Attachment)
            $attachment.ContentDisposition = $contentDisposition
            $attachment.ContentTransferEncoding = [MimeKit.ContentEncoding]::Base64
            $attachment.FileName = [System.IO.Path]::GetFileName($file)        
            #https://github.com/jstedfast/MimeKit/blob/master/FAQ.md#UntitledAttachments
            # The following sentense will also work.
            # $attachment.ContentDisposition.Parameters[0].EncodingMethod = [MimeKit.ParameterEncodingMethod]::Rfc2047
            foreach ($param in $attachment.ContentDisposition.Parameters) {
                $param.EncodingMethod = [MimeKit.ParameterEncodingMethod]::Rfc2047
            }
            $multiPart.Add($attachment)
        }
        $message.Body = $multiPart
    } else {
        $message.Body = $textPart
    }   

    $client = New-Object MailKit.Net.Smtp.SmtpClient
    $client.Connect($smtpServer, $port, $false)
    $client.Authenticate($user, $password)
    $client.Send($message)
    $client.Disconnect($true)
}

使い方

関数を呼び出す際はSplattingを使うと分かりやすいと思います。

$args = @{
ToArray = @("recipient1@bar.com","recipient2@bar.com")
Subject = "件名"
Body = @"
こんにちは。
これは本文です。
"@
FileArray = @("C:\Temp\新しいテキスト ドキュメント.txt")
}
Send-JisMail @args

Outlookで受信すると添付ファイル名が"ATT0####.dat"になってしまう問題について

MimeKitのFAQにあるとおり、Outlookは RFC 2231 に対応しておらず文字化けすることがあります。上述のコードではFAQに合わせて RFC 2047 を使うようにしています。
参考: 添付ファイルにおける日本語のファイル名に関して

No comments:

Post a Comment