「メーラーやWebメールを利用せずに所定のメールを送信したい」
このようなケースはよくあります。以下のような事例です。
- 外部システム(SalesforceのようなCRM・データウェアハウス等)と自動連携させた結果をメールで通知する
- 長時間の自動処理(Windowsのバッチ処理等)が完了後に、作業完了のアナウンスをメールで通知する
ここでは、「メーラーやWebメールでユーザ操作することなく、所定のタイミングでメール送信するツール」をどのように作成するのか紹介します。
PowerShellを使用してメールを送信する
まずは、PowerShellのファイル単独で「単純なメール送信を行う機能」を雛形として実現します。
# ----------------------------------------------
# メール情報
# ----------------------------------------------
$mail = @{
smtp_server = "送信メールサーバーのドメインを記載(例:smtp.sample.com)";
smtp_port = 587;
user = "メールサーバーアクセスユーザ(例:username@sample.com)";
password = "メールサーバーアクセスユーザのパスワード(平文パスワード)";
from = "送信元メールアドレスを記載";
to = "宛先(To)メールアドレスを記載";
cc = "宛先(Cc)メールアドレスを記載";
}
$password = ConvertTo-SecureString $mail["password"] -AsPlainText -Force;
$credential = New-Object System.Management.Automation.PSCredential $mail["user"], $password;
# ----------------------------------------------
# メールフォーム
# ----------------------------------------------
$subject = "テストメール";
$crlf = "`r`n";
$body = "これはテストメールです。" + $crlf;
$body += "これはテストメールです。" + $crlf;
# ----------------------------------------------
# メール送信
# ----------------------------------------------
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { return $true }
Send-MailMessage -To $mail["to"] `
-Cc $mail["cc"] `
-From $mail["from"] `
-SmtpServer $mail["smtp_server"] `
-Subject $subject `
-Body $body `
-Credential $credential `
-Port $mail["smtp_port"] `
-Encoding UTF8 `
-UseSsl
Code language: PowerShell (powershell)
エラーチェック等の詳細な処理は含めず、バスワード情報も暗号化せずに平文のテキスト文字をそのまま記述する形式です。
ポート番号は
- 「SMTP認証(SMTP Auth)」のみを行う場合 587
- 「SMTP over SSL」による暗号化通信でメールサーバーに接続する場合 465
のどちらかを指定します。587はサブミッションポートの番号です。
メールサーバーが対応しているならば、後者の465が望ましいです。この場合でも「SMTP認証(SMTP Auth)」は行われます。
ここまででメール送信が可能です。実際にPowerShellを実行しメール送信がされることを確認してください。
メールアドレスの設定パスワードを暗号化保存し、利用するように変更する
雛形として作成したPowerShellには、大きな問題があります。
「パスワードが平文のまま記載されており、アカウント情報が流出してしまう恐れがある」
そこで次に、パスワード情報を暗号化して利用できるように、PowerShellを変更します。
まずは暗号化パスワードファイルの作成です。
以下3行のみを記載したPowerShellプログラムを別途作成し、実行してください。$FilePathで指定するファイル名は極力、暗号化対象となるユーザー情報が判別不可能な名前にする方がより安全です。
$FilePath = "暗号化パスワードを保存するファイル名"
$Credential = Get-Credential
$Credential.Password | ConvertFrom-SecureString | Set-Content $FilePath
Code language: PowerShell (powershell)
実行すると、ユーザ名とパスワードを入力する画面が起動します。
それぞれ入力すると、$FilePath変数で指定していたたファイルへ、ユーザ情報とパスワード情報が暗号化された形式で保存されます。
次は、雛形としていたメール送信用のPowerShellプログラムの編集です。
平文パスワードをそのまま利用していた箇所を、先程保存した暗号化パスワードファイルから読み出し、パスワード変数($passwd)に渡すように変更します。
- $Arg1と$Arg2をパラメータとする記載を追加し、暗号化パスワードファイルとユーザID情報を引数として入力できるように変更
- 暗号化パスワードファイルからパスワード情報を抽出
- メール情報を固定情報→取得した情報に変更
引数入力とパスワード抽出については、以下の内容を記載します。雛形のPowerShellプログラムの先頭から追加すればOKです。
param($Arg1,$Arg2)
$passwdfile = $Arg1
$userid = $Arg2
# 暗号化パスワードファイルから暗号化情報を取得
$encrypted = Get-Content $passwdfile | ConvertTo-SecureString
# ユーザー情報を元に認証情報(パスワード)を取得
$PsCredential = New-Object System.management.Automation.PsCredential($userid, $encrypted)
$passwd = $PsCredential.GetNetworkCredential().Password
Code language: PowerShell (powershell)
userとpassword情報は以下の箇所を変更します。
# ----------------------------------------------
# メール情報
# ----------------------------------------------
$mail = @{
smtp_server = "送信メールサーバーのドメインを記載(例:smtp.sample.com)";
smtp_port = 587;
user = $userid;
password = $passwd;
from = "送信元メールアドレスを記載";
to = "宛先(To)メールアドレスを記載";
cc = "宛先(Cc)メールアドレスを記載";
}
Code language: PowerShell (powershell)
$Arg1と$Arg2の情報は、バッチプログラムを追加で作成し、バッチプログラムからPowerShellを実行する際に受け取るように変更します。作成するバッチプログラムの内容を以降に説明します。
バッチプログラムから、メール送信用PowerShellを実行するように変更する
作成したメール送信用のPowerShellプログラムを実行するとしても、条件に合致する場合にのみメール送信を行ったり、値を受け渡して実行したいことがあります。
今回は、バッチプログラムとここまでに作成したPowerShellプログラムの組み合わせで
「暗号化したユーザー情報をPowerShellプログラムに渡し、メール送信を実行する」
ように変更します。
作成するバッチプログラムの例としては、以下のようにします。
@echo off
cd /d %~dp0
rem mail.ps1 作成したメール送信用のPowerShellプログラム名を記載
rem filename 暗号化パスワードファイル名を記載
rem username メールアドレス(メールアカウントのID)を記載
cmd /k powershell -NoProfile -ExecutionPolicy Unrestricted .\mail.ps1 filename username
Code language: DOS .bat (dos)
ここまでで変更は完了です。バッチプログラムを実行すると、暗号化パスワード情報とメールアドレス情報を利用してPowerShellが実行され、メール送信ができることを確認してください。
以上に記載した内容までが、多くのケースに転用できるメール送信ツールの雛形となります。
作業内容に応じてカスタマイズし、業務を効率化していきましょう。
(参考)VBScriptを使用してメールを送信する
経験上、前述のPowerShellほど活用できる場面は多くありませんが、VBScriptを利用してメール送信を行うことも可能です。
単純にメール送信のみを行うものであれば、以下のようになります。
Dim oMsg
Set oMsg = CreateObject("CDO.Message")
' ---------------------------------------------------------------------------------
' メールヘッダ、テキストの設定
' ---------------------------------------------------------------------------------
oMsg.From = "送信元メールアドレス"
oMsg.To = "送信先メールアドレス"
oMsg.Subject = "バッチ実行メールの件名"
oMsg.TextBody = "バッチ実行完了しました。"
oMsg.BodyPart.Charset = "Shift-JIS"
' ---------------------------------------------------------------------------------
' 送信サーバー・アクセス情報の設定
' 環境に応じて置き換える項目:
' sendusing:外部メールサーバーへ接続する場合は2
' smtpserver:メールサーバーのホスト名
' smtpserverport:メールサーバーへのSMTPアクセス用ポート番号(25 or 465 or 587)
' smtpusessl:SSLでのSMTPアクセス(SMTP over SSL)となる場合はTrueに設定
' smtpauthenticate:Basict認証 1 or NTLM認証 2
' sendusername:サーバへ接続する際のアカウント(メールアドレスあるいはID情報)
' sendpassword:サーバへ接続する際のアカウントの設定パスワード
' smtpconnectiontimeout:メールサーバーとの接続タイムアウト(秒)
' ---------------------------------------------------------------------------------
strConfigurationField ="http://schemas.microsoft.com/cdo/configuration/"
With oMsg.Configuration.Fields
.Item(strConfigurationField & "sendusing") = 2
.Item(strConfigurationField & "smtpserver") = "メールサーバーのアドレス"
.Item(strConfigurationField & "smtpserverport") = 587
.Item(strConfigurationField & "smtpusessl") = False
.Item(strConfigurationField & "smtpauthenticate") = 1
.Item(strConfigurationField & "sendusername") = "メールアドレス"
.Item(strConfigurationField & "sendpassword") = "メールアドレスのパスワード"
.Item(strConfigurationField & "smtpconnectiontimeout") = 30
.Update
end With
oMsg.Send
Set oMsg = Nothing
Code language: VBScript (vbscript)
例ではポート番号を587としていますが、もしSMTP over SSLでメール送信を行うのであれば、その場合はsmtpserverport、smtpusesslの箇所をそれぞれ465、Trueと設定します。
メール送信処理の完了後に、確保したMessageオブジェクト(oMsg)のメモリ領域を開放しています。
この内容を雛形として、カスタマイズしていくと良いです。