Home > Windows にまつわる e.t.c.

PowerShellでメール送信


Server管理をしていると、PowerShellからメール送信する機会は多いですね。

PowerShell Vertion 3 以降であれば Send-MailMessage コマンドレットが使えますが、より汎用的に SmtpClient で関数実装してみました。

spam 誤認対策で DNS に FQDN が登録されているホストの場合は、HELO 時に FQDN を渡すようにしています。(.NET Framework 4.0 以降)
FQDN セット用に app.config をスクリプトが置いてあるフォルダに出力するので、.ps1 に組み込んで使用してください。

認証用アカウントとパスワードを渡せば Submission します。(省略時は SMTP)

echo は動作確認用なので、不要なら削除してかまいません。

# メール送信
function SendMail(
        $MSA,               # メールサーバー
        $MailFrom,          # 送信元
        $RcpTos,            # 宛先
        $Subject,           # タイトル
        $Body,              # 本文
        $AuthUser,          # SMTP Auth アカウント
        $Password           # SMTP Auth パスワード
    ){

    #  .NET Framework 4.0 以降の場合
    if($PSVersionTable.CLRVersion.Major -ge 4){
        # FQDN を求める
        $Data = nslookup $env:computername | Select-String "名前:"
        if( $Data -ne $null ){
            $Part = -split $Data
            $FQDN = $Part[1]
        }

        # FQDN が DNS に登録されているホストの場合
        if( $FQDN -ne $null ){
            # app.config を作成する
            if( $PSVersionTable.PSVersion.Major -ge 3 ){
                $ScriptDir = $PSScriptRoot
            }
            # for PS v2
            else{
                $ScriptDir = Split-Path $MyInvocation.MyCommand.Path -Parent
            }
            $AppConfig = Join-Path $ScriptDir "app.config"
@"
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.net>
        <mailSettings>
            <smtp>
                <network
                    clientDomain="$FQDN"
                />
            </smtp>
        </mailSettings>
    </system.net>
</configuration>
"@ | set-content $AppConfig -Encoding UTF8

            # HELO 申告ホスト名に FQDN をセットする
            [AppDomain]::CurrentDomain.SetData("APP_CONFIG_FILE", $AppConfig)
            Add-Type -AssemblyName System.Configuration
        }
    }

    # メールデーター
    $Mail = New-Object Net.Mail.MailMessage

    # 送信元
    $Mail.From = $MailFrom
    echo "[INFO] From: $MailFrom"

    # 宛先
    foreach( $RcpTo in $RcpTos ){
        $Mail.To.Add($RcpTo)
        echo "[INFO] To: $RcpTo"
    }

    # タイトル
    $Mail.Subject = $Subject
    echo "[INFO] Subject: $Subject"

    # 本文
    $Mail.Body = $Body
    echo "[INFO] Body: $Body"

    # メール作成
    echo "[INFO] MSA: $MSA"

    # Submission
    if( $AuthUser -ne $null ){
        if( $Password -ne $null ){
            echo "[INFO] SMTP Auth Account : $AuthUser"
            $SmtpClient = New-Object Net.Mail.SmtpClient($MSA, 587)
            $SmtpClient.Credentials = New-Object System.Net.NetworkCredential($AuthUser, $Password)
        }
        else{
            echo "[ERROR] SMTP Auth パスワードがセットされていない"
            return
        }
    }
    # SMTP
    else{
        $SmtpClient = New-Object Net.Mail.SmtpClient($MSA)
    }

    # メール送信
    echo "[INFO] Mail send"
    try{
        $SmtpClient.Send($Mail)
    }
    catch{
        $Now = Get-Date
        $ExecTime = "{0:0000}-{1:00}-{2:00} " -f $Now.Year, $Now.Month, $Now.Day
        $ExecTime += "{0:00}:{1:00}:{2:00}.{3:000} " -f $Now.Hour, $Now.Minute, $Now.Second, $Now.Millisecond
        echo "[ERROR] $ExecTime メール送信に失敗しました"
    }

    $Mail.Dispose()

    return
}

 

こんな感じで使います

$MSA = "mail.contoso.com"
$MailFrom = "example-form@contoso.com"
$RcpTos = @("example-to@contoso.com")
$Subject = "これはテストメールです"
$Body = @"
てすと
てすと
"@
$AuthUser = "hogehoge"
$Password = "P@ssW0rd"

SendMail $MSA $MailFrom $RcpTos $Subject $Body $AuthUser $Password

 

当初 [System.Net.Dns]::GetHostEntry($env:COMPUTERNAME).Hostname で FQDN を取得しようとしたのですが、この方法で FQDN を取得すると、app.config に FQDN をセットしても FQDN を喋ってくれなくなるので、nslookup で FQDN 取得って力技にしちゃいました。

 

back.gif (1980 バイト)

home.gif (1907 バイト)

Copyright © MURA All rights reserved.