Надсилання електронної пошти через powershell (Net.Mail.SmtpClient або Send-Mailmessage) працює, але не при виклику планувальника завдань


0

Я зробив скрипт, щоб перевірити статус UPS, зареєструвати його та надіслати повідомлення електронної пошти. Сценарій працює відмінно, якщо виконується вручну, але при виконанні за допомогою планувальника завдань він не надсилає електронну пошту . Він робить все інше, хоча (наприклад, він правильно входить до файлу), тому я не розумію, що відбувається.

Будь-який натяк і / або пояснення? Дуже дякую!

Ось сценарій:

<#
.SYNOPSIS
Skript pro test stavu napájení (AC, nebo UPS)
.DESCRIPTION
Zjistí stav napájení, a pokud to není AC, ale baterie, pole notifikační e-mail. Stejně tak ho pole, pokud ádná baterie připojena není.
.PARAMETER none
no parameters
.EXAMPLE
no example needed
.NOTES
crysman (copyleft) 2016
# changelog:
# ...         next version - don't forget to update the $scriptVersion variable!
# 2016-03-10  přidány barvy výstupů, help, upraveny exit codes a návratové hodnoty, upraven hostname
# 2016-03-09  opraveno logování, vč. loggingu nefunkčních mailnotifikací
# 2016-03-08  initial release
#>
$scriptVersion = '2016-03-10'
$scriptName = $MyInvocation.mycommand.name
$timestamp = [datetime]::now.tostring("yyyy-MM-dd_HH-mm")
$hostName = [system.environment]::MachineName.ToLower()


#funkce pro posílání notifikačních mailů
#v.1.2
function sendEmail($Subject, $Body){
  $EmailTo = "it@XXXYOURFAVOURITEDOMAIN.cz"
  $EmailFrom = "$global:hostName@XXXYOURFAVOURITEDOMAIN.cz"
  $SMTPServer = "smtp.XXXYOURFAVOURITEDOMAIN.cz"
  $SMTPClient = New-Object Net.Mail.SmtpClient($SMTPServer, 587)
  $SMTPClient.EnableSsl = $true
  $SMTPClient.Credentials = New-Object System.Net.NetworkCredential("notifications@XXXYOURFAVOURITEDOMAIN.cz", "XXXYOURFAVOURITEPASSWORD");
  $Body = "$Body `n-----`nscript $global:scriptName v.$global:scriptVersion on host $global:hostName`ntimestamp: $global:timestamp"
  #Write-Host $EmailTo $EmailFrom $Subject $Body
  try {
    $SMTPClient.Send([string]$EmailFrom,[string]$EmailTo,[string]$Subject,[string]$Body)
  }
  catch {
    $msg = "$global:timestamp WARNING: notification e-mail has NOT been sent, please check SMTP credentials"
    Write-Host "ERR: " $Error[0].ToString() -ForegroundColor Red
    #následující řádek nefunguje - proč? :( - do souboru se zapisuje, ale na screen ne!
      #Write-Output $msg | Tee -Append -FilePath $global:errorLog
    Write-Host $msg -ForegroundColor Red
    Write-Output $msg | Out-File -Append $global:errorLog
    return $false
  }
  finally {
    $SMTPClient.Dispose()  
  }
  Write-Host "notification e-mail has been sent succesfully" -ForegroundColor Gray
  return $true
}

$scriptDir = "D:\scripts"
$log = "$scriptDir\checkPowerUPS-error.log"
$errorLog = $log


# kategorie stavů baterie viz https://msdn.microsoft.com/en-us/library/aa394074(v=vs.85).aspx
$bStats= @{"1"="battery is discharging";"2"="On AC";"3"="Fully Charged";"4"="Low";"5"="Critical";"6"="Charging";"7"="Charging and High";"8"="Charging and Low";"9"="Charging and Critical";"10"="Undefined";"11"="Partially Charged";} 

# aktuální stav:
$powerStat=Get-WmiObject -class Win32_Battery -ComputerName localhost
$bStat=$powerStat.BatteryStatus
$bStatText=$bStats["$bStat"]
$bStatRemaining=$powerStat.EstimatedRunTime

#zapíeme do EventLogu, popř. poleme mail
#nachystat EventLog
$eLog = $scriptName #pouijeme název skriptu
if (! $eLog) {
  Write-Output "$timestamp něco je patně s powershellem (?)" | tee -Append -FilePath $log
  exit 99  
}
$eLogExists = get-EventLog -LogName Application -Source "$eLog"
if (! $eLogExists){
  echo "WARNING: jetě neexistuje eventlog, vytvářím..."
  new-EventLog -LogName Application -Source "$eLog"
}
#zalogovat a notifikovat
if (!($powerStat) -or $bStat -eq 1 -or $bStat -eq 4 -or $bStat -eq 5) { 
  if(!$powerStat){
    #(nemáme UPS)
    $Subject = "IMPORTANT: Power without UPS on $hostName"
    $Body = "this host seems NOT to be connected to any battery/UPS"
  } else {
    #(UPS máme, ale nějaký non-AC status)
    $Subject = "IMPORTANT: Power failure on $hostName"
    $Body = "battery status is $bStat ($bStatText), estimated remaining battery time: $bStatRemaining min"
  }
  #vypsat na screen a zalogovat:
  Write-Output "$timestamp $Body" | Out-File -Append $log
  Write-Host "$timestamp $Body" -ForegroundColor Red
  Write-EventLog -LogName Application -Source "$eLog" -EntryType Warning -EventId 11 -Message "$eLog skončil neúspěně - $Body"
  #poslat maila:
  $mailsent = sendEmail $Subject $Body
  if ($mailsent) {$exitcode=1} else {$exitcode=2}
} else {
  $exitcode = 0
  Write-Host "OK, $hostName is on AC (status $bStat)`nscript $scriptName v.$scriptVersion" -ForegroundColor Green
}
exit $exitcode

Ось завдання:

<Task xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task" version="1.2">
<RegistrationInfo>
<Date>2016-03-07T16:53:24.9000439</Date>
<Author>SERVER-XXX\myadminaccount</Author>
</RegistrationInfo>
<Triggers>
<CalendarTrigger>
<Repetition>
<Interval>PT1M</Interval>
<StopAtDurationEnd>false</StopAtDurationEnd>
</Repetition>
<StartBoundary>2016-03-07T00:00:00</StartBoundary>
<Enabled>true</Enabled>
<ScheduleByDay>
<DaysInterval>1</DaysInterval>
</ScheduleByDay>
</CalendarTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>SERVER-XXX\myadminaccount</UserId>
<LogonType>Password</LogonType>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>StopExisting</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>true</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT1H</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>powershell</Command>
<Arguments>
-NonInteractive -Noprofile -Command "&{D:\scripts\checkPowerUPS.ps1}"
</Arguments>
</Exec>
</Actions>
</Task>

Операційна система: Windows Server 2012 R2

PS: Я переглядав як Technet, так і різні сайти Stack Exchange, щоб вирішити це, але не пощастило: / Отже, намагаюся тут ...


Натомість поза темою, але мені цікаво, чому ви використовуєте .NET SmtpClient класу для надсилання електронної пошти замість рідного Send-Mailmessage cmd-let?
Smeerpijp

@doenoe Тому що я не зрозумів, як застосувати аутентифікацію за допомогою цього cmd-let. Якщо ви знаєте як, дайте мені знати.
crysman

Подивись на це Стаття TechNet. Є -Credential параметр. У статті також є приклад: send-mailmessage -to "User01 <user01@example.com>" -from "ITGroup <itdept@example.com>" -cc "User02 <user02@example.com>" -bcc "ITMgr <itmgr@example.com>" -subject "Don't forget today's meeting!" -credential domain01\admin01 -useSSL
Smeerpijp

Добре, я переключився на Send-MailMessage cmd-let. Однак нічого не змінилося. Запуск вручну робить все як передбачається, в тому числі відправляючи повідомлення електронної пошти. Планувальник завдань повідомляє код виходу 0, все виглядає чудово, є нові рядки в журналі файлів, з'являються нові журнали в системі Event Viewer, але NO E-MAIL відправляється! :(
crysman

Хм, добре, у мене є графік завдання, яке запускає сценарій PS, і відправляє пошту, коли це буде зроблено, це мої параметри завдання в скрипті програми на вкладці дій: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe Аргументи: -command "& 'C:\Scripts\asabackup\asabackup.ps1'" Почати з: C:\Scripts\asabackup Можливо, ви можете налаштувати значення, щоб вони відповідали моїм (з вашим власним робочим каталогом тощо) і знову перевірити їх
Smeerpijp

Відповіді:


1

Після декількох годин налагодження, я отримав його.

Проблема:

використання -Command "..." аргумент у планувальнику завдань.

Рішення:

Використовуйте -File "..." замість цього аргументу. У цьому випадку це буде:

<Exec>
<Command>powershell</Command>
<Arguments>
-NonInteractive -Noprofile -File "D:\scripts\checkPowerUPS.ps1"
</Arguments>
</Exec>

Деталі:

При використанні -Command "&{D:\testScript.ps1}", глобальні змінні, оголошені в сценарії, недоступні, тобто. це не працюватиме:

$myVar = "ham"
function myF(){
  Write-Output $global:myVar
}
myF

Я не знайшов відповіді на моє вирішене проблемою помилку: "Яка різниця між -Command і -File Аргумент PowerShell? " Виклик powershell /? не допомагає мені так чи інакше, тому що він нічого не говорить про глобальні та / або будь-які "напівглобальні" змінні. Більше того, він стверджує, що використовує -Command:

... Виконує вказані команди (і будь-які параметри), як якщо б вони були набрані в командному рядку Windows PowerShell ...

Що не відповідає дійсності, тому що запуск свіжого вікна PowerShell і виконання рядків, які я вкладаю у приклад коду вище з $ myVar, буде працювати, тоді як виконання прикладу з -Command ... не буде.

Сподіваюся, це допоможе вам.


Схоже, що джерелом проблеми є саме те, де Invoke-Command малює лінію між локальним і віддаленим. (Я вважаю Invoke-Command використовується для сцени PowerShell -Command Параметр.) Ви можете використовувати -ArgumentList (напівдорозі цієї документації ) для вирішення проблеми.
jpaugh
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.