適材適所

PowerShellやVBAなどのプログラミングに関すること、キャリア、子育ての3本で書いていきます

PowerShellからGmailを送信するスクリプトを作りました

GmailのAPI経由でメールを送るのでセキュリティも安心!!

できること

メールの送信

Send-Gmail.ps1 -subject "件名" -bodyText "本文"

添付ファイル

Send-Gmail-subject "件名" -bodyText "本文" -filePath "C:\test.txt"

PowerShellでGoogle APIを使う準備

Gmail APIのページを参照ください。

こちらの記事も参考になるかも。

Google API以外にMimeKitというライブラリを利用します。

コード

##########################################################
## Send-Gmail.ps1
##Gmailを経由してメールを送信する。
##予めGoogle API Consoleから認証用のcrdentials.jsonを取得し、
##このスクリプトと同じディレクトリに保存する。
##Nugetから必要なライブラリをダウンロードしてくる。
##ライブラリのバージョンも.NETのバージョンも決め打ち。
##
##例:
## Send-Gmail.ps1 -to to@gmail.com -from from@gmail.com -subject "件名"
##-bodyText "本文だよ☆" -filePath "添付ファイルのパスだよ☆"
##########################################################
param(
   [parameter(mandatory)]$to,
   [parameter(mandatory)]$from,
   [parameter(mandatory)]$subject,
   [parameter(mandatory)]$bodyText,
   $filePath
)

#packageの読み込み準備
$dir="$PSScriptRoot\"
$package=@(
   ("Newtonsoft.Json","12.0.3"),
   ("Google.Apis.Core","1.46.0"),
   ("Google.Apis","1.46.0"),
   ("Google.Apis.Auth","1.46.0"),
   ("Google.Apis.Gmail.v1","1.46.0.1992"),
   ("BouncyCastle","1.8.5"),
   ("MimeKit","2.8.0")
)

#dllのインストール
for($i=0;$i -lt $package.Count;$i++){
   $name=$package[$i][0]
   $version=$package[$i][1]
   if(!(Test-Path "$dir$name.$version")){
      Install-Package $name -Source nuget -Scope CurrentUser -SkipDependencies -Destination $dir -RequiredVersion $version|out-null
   }
}

##アセンブリの読み込み(汚いコードですんません)
$target="net45"
for($i=0;$i -lt $package.Count;$i++){
   $name=$package[$i][0]
   $version=$package[$i][1]
   $parent=Join-Path $dir "$name.$version\lib\$target"
   if(Test-Path ($parent)){
      $path="$parent\$name.dll"
   }else{
      $path= (dir -Filter "$name*.dll" -path (Join-Path $dir "$name.$version") -Recurse)[0].fullName
      $parent=[System.IO.Path]::GetDirectoryName($path)
   }
   $refPath=$null
   if((dir -Filter "$name*.xml" -Path $parent).Length -gt 0){$refPath=(dir -Filter "$name*.xml" -path $parent)[0].fullName}
   if($refPath -ne $null){
      Add-Type -path $path -ReferencedAssemblies $refPath|Out-Null
   }else{
      Add-Type -path $path|Out-Null
   }
}

[string[]]$scope=[Google.Apis.Gmail.v1.GmailService+Scope]::GmailSend
$ApplicationName = "Gmail API .NET Quickstart";
$open=[System.IO.FileMode]::Open
$read=[System.IO.FileAccess]::Read
$stream= New-Object System.IO.FileStream -ArgumentList (Join-Path $dir "credentials.json"),$open,$read
$secrets=([Google.Apis.Auth.OAuth2.GoogleClientSecrets]::Load($stream)).Secrets
$credPath=(Join-Path $dir "gmail_token.json")
$dataStore=[Google.Apis.Util.Store.FileDataStore]::new($credPath,$true)
$credential=
([Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker]::AuthorizeAsync(
$secrets,$scope,"user",[System.Threading.CancellationToken]::None,$dataStore)).Result;


##Create Gmail API service.
$baseClient=New-Object Google.Apis.Services.BaseClientService+Initializer
$baseClient.HttpClientInitializer =$credential
$baseClient.ApplicationName=$ApplicationName
$service=New-Object Google.Apis.Gmail.v1.GmailService($baseClient)

$email= New-Object MimeKit.MimeMessage
$email.From.Add((New-Object MimeKit.MailboxAddress -ArgumentList $from,$from))
$email.To.Add((New-Object MimeKit.MailboxAddress -ArgumentList $to,$to))
$email.Subject=$subject
$textFormatPlain=[MimeKit.Text.TextFormat]::Plain
$textPart=New-Object MimeKit.TextPart -ArgumentList $textFormatPlain
$textPart.SetText([System.Text.Encoding]::GetEncoding('iso-2022-jp'),$bodyText)

if(($filePath -ne $null) -and (Test-Path $filePath)){
   #添付ファイルの処理
   $attachment=New-Object MimeKit.MimePart
   $content=New-Object MimeKit.MimeContent([System.IO.File]::OpenRead($filePath),[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($filePath)
   $multiPart = New-Object MimeKit.Multipart("mixed")
   $multiPart.Add($textPart)
   $multiPart.Add($attachment)
   $email.Body=$multiPart
}else{
   $email.Body=$textPart
}

$raw=([System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($email.ToString()))).TrimEnd('=').Replace('+', '-').Replace('/', '_')
$message=New-Object Google.Apis.Gmail.v1.Data.Message
$message.Raw=$raw

$mail=$service.Users.Messages.Send($message,"me").Execute()
$mail.id

おわりに

特に何かに使う予定はないのですが、Google API面白いなぁと思って作りました。

何かに応用できるかも知れないので書き残しておきます。

ここまでお読みいただき、ありがとうございました。

参考

Users.messages: send  |  Gmail API  |  Google Developers

c# - Gmail APIメッセージの作成方法

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