Теги тела HTML в Powershell

#html #powershell

#HTML #powershell

Вопрос:

Я новичок в Powershell и HTML. Я использую код Powershell в HTML-файле для отображения критериев истечения срока действия паролей AD и, наконец, отправки его по электронной почте. Генерируемое электронное письмо правильно отображает верхний и нижний колонтитулы, но средняя часть кода, которая запрашивает объявление, не показывает никаких строк в таблице HTML. Я подозреваю, что в моем использовании $body = что-то не так, но именно так предлагается в документации. Также, когда я индивидуально запускаю командлеты Powershell, я вижу, что возвращаются записи. Может кто-нибудь, пожалуйста, подсказать, где я могу ошибаться?

  #Remove Digital Signature Check
Set-ExecutionPolicy Unrestricted

 import-module activedirectory
# $ErrorActionPreference = 'SilentlyContinue'

$MailParams = @{
To = @("iq@mail.com")
From = "iq@mail.com"
Subject = "HTML Table"
SmtpServer = "mail.server.com"
}
  
 try {
   
            
        $body = 
        "<div>
            <p>
                <b><span >Attention IT Group:</span></b>
            </p>
            <BR>
          </DIV>

          <table border=0 cellspacing=0 cellpadding=0 width=94%>
            <tbody>
                <tr>
                    <td colspan=2 style='width:100.0%; border:solid #1F4E79 1.0pt; background:#1F4E79; padding:0cm 5.4pt 0cm 5.4pt'
                        <p >
                            <SPAN style='font-size:22.0pt; font-weight:bold; font-family:amp;quot;Arialamp;quot;,sans-serif; color:white'>
                                Password Expirations for Service Accounts 
                            </SPAN>
                        </P>
                    </td>
                </tr>"
# **** Need Code for Expire within < 1 Day ******
        $body  =    Get-ADUser -Filter {Enabled -eq $True}  -SearchBase "OU=Service Accounts,OU=SG1,OU=TAW,DC=wt,DC=ad,DC=cit,DC=com" `
                 -Properties * | 
                 Sort-Object -Descending -Property  @{Expression={($_.PasswordLastSet.AddDays(365) - [DateTime]::Now).Days}}|
                # sort-object -Descending -property SamAccountName |  
                 Where-Object{($_.PasswordLastSet.AddDays(365) - [DateTime]::Now).Days -le  1 }|
    Select-Object -property `
           @{Name="LogonName";Expression={$_.SamAccountName}} ,
            @{Name="PasswordExpiration";Expression={$_.PasswordLastSet.AddDays(365).ToString("dd-MMM-yyyy")}}  |
    convertto-HTML -Fragment 

# **** Need Code for Expire within 7 Days ( 2 - 7 Days) ******
        $body  =   Get-ADUser -Filter {Enabled -eq $True}  -SearchBase "OU=Service Accounts,OU=SG1,OU=TAW,DC=wt,DC=ad,DC=cit,DC=com" `
                 -Properties * | 
                 Sort-Object -Descending -Property  @{Expression={($_.PasswordLastSet.AddDays(365) - [DateTime]::Now).Days}}|
                # sort-object -Descending -property SamAccountName |  
                 Where-Object{($_.PasswordLastSet.AddDays(365) - [DateTime]::Now).Days -in (2,7) }|
    Select-Object -property `
           @{Name="LogonName";Expression={$_.SamAccountName}} ,
            @{Name="PasswordExpiration";Expression={$_.PasswordLastSet.AddDays(365).ToString("dd-MMM-yyyy")}}  |
    convertto-HTML -Fragment 

# **** Need Code for Expire within 7 Days ( 8 - 15 Days) ******
        $body  =   Get-ADUser -Filter {Enabled -eq $True}  -SearchBase "OU=Service Accounts,OU=SG1,OU=TAW,DC=wt,DC=ad,DC=cit,DC=com" `
                 -Properties * | 
                 Sort-Object -Descending -Property  @{Expression={($_.PasswordLastSet.AddDays(365) - [DateTime]::Now).Days}}|
                # sort-object -Descending -property SamAccountName |  
                 Where-Object{($_.PasswordLastSet.AddDays(365) - [DateTime]::Now).Days -in (8,15) }|
    Select-Object -property `
           @{Name="LogonName";Expression={$_.SamAccountName}} ,
            @{Name="PasswordExpiration";Expression={$_.PasswordLastSet.AddDays(365).ToString("dd-MMM-yyyy")}}  |
    convertto-HTML -Fragment 


# **** Need Code for Expire within 7 Days (16- 30  Days) ******
        $body  =  Get-ADUser -Filter {Enabled -eq $True}  -SearchBase "OU=Service Accounts,OU=SG1,OU=TAW,DC=wt,DC=ad,DC=cit,DC=com" `
                 -Properties * | 
                 Sort-Object -Descending -Property  @{Expression={($_.PasswordLastSet.AddDays(365) - [DateTime]::Now).Days}}|
                # sort-object -Descending -property SamAccountName |  
                 Where-Object{($_.PasswordLastSet.AddDays(365) - [DateTime]::Now).Days -in (16,30) }|
    Select-Object -property `
           @{Name="LogonName";Expression={$_.SamAccountName}} ,
            @{Name="PasswordExpiration";Expression={$_.PasswordLastSet.AddDays(365).ToString("dd-MMM-yyyy")}}  |
    convertto-HTML -Fragment  

#*****   Footer of Email****
    $body  = "   </tbody>
               </table>
                <BR>
                <p style='margin-bottom:2.0pt'>
                    <span style='font-family:amp;quot;Calibriamp;quot;,sans-serif; color:black'> Management team<br> </span><span style='color:black'>
                    </span>
                </p>
                <BR>
             " 
    $MailParams.body = $body
                                         
}


catch { 
write-output "No records found for one of the criteria" 
} 
 
Send-MailMessage @MailParams -BodyAsHtml
  

Комментарии:

1. ConvertTo-Html -Fragment по-прежнему будет выводить автономный <table> элемент, поэтому вы вкладываете новые <table> элементы в тот, который у вас уже есть. Отображаются ли записи, если вы просматриваете необработанный HTML-код получаемого сообщения электронной почты?

2. Это вызывает Get-ADUser 3x. Предлагаю разделить это по-другому. Извлеките данные один раз в коллекцию. Фильтр в три меньшие коллекции. Используйте эти коллекции для создания электронных писем. Кроме того, сделайте так, чтобы он работал как обычный текст, экспортируемый в CSV. Это позволит вам устранить неполадки с фильтрацией и тому подобное. Затем заставьте его экспортировать обычное текстовое электронное письмо в текстовый файл, что позволит устранить неполадки при создании электронного письма. Затем преобразуйте его в вывод html, чтобы вы могли устранить неполадки при генерации html. Другими словами, сначала добейтесь того, чтобы извлечение данных работало на 100%. Затем поэтапно повышайте сложность.

3. Xalorous, именно так мы подошли к этому, но требования пользователя изменились, поэтому нам пришлось добавить некоторую сложность в код. Матиас, записи появляются, если я проверяю необработанный вывод html, так почему же он не отображается в электронном письме? Спасибо вам обоим за ваши ценные предложения, надеюсь, я смогу решить эту проблему с помощью этого форума.

Ответ №1:

Это не будет полным ответом, и я в основном повторяю то, что люди уже сказали. Особенно комментарий, чтобы не вызывать Get-ADUser три раза.

  • Ваш Get-Aduser должен быть отфильтрован с помощью запроса — не возвращайте каждую включенную учетную запись, а затем используйте Where предложение. Я предполагаю, что вам нужны учетные записи с последней установленной датой ввода пароля за 30 дней до того, какой будет 1-летняя годовщина даты ввода пароля? Возьмите все из них, а затем используйте свое Where предложение для результатов.
  • Отделите код, в котором вы создаете отчет о рекламе, от кода, в котором вы создаете HTML. И отделите это от кода, в котором вы создаете почтовое сообщение. В настоящее время у вас есть три разных процесса, соединенных вместе, и это усложняет устранение неполадок.
  • Выводите свои фрагменты в виде HTML-файлов и тестируйте их по отдельности. Outlook действительно придирчив к отображаемому HTML <div> -коду и <span> может стать драмой. Конечно, они работают в Outlook, но иногда какая-то комбинация не работает. Я стараюсь сделать это как можно проще.

Вот пример того, как может работать фильтр AD и последующая нарезка.

 $1year = (get-date).AddDays(-365)
$30days = (get-date).AddDays(-334)
$tomorrow = (get-date).AddDays(-364)
$15days = (get-date).AddDays(-350)

# Get all the users that will be included in the report - one AD query
$users = get-aduser -filter 'passwordlastset -gt $1year -and passwordlastset -lt $30days -and enabled -eq "True"' `
    -properties passwordlastset -searchbase "OU=myOU,DC=example,DC=com"

# break down the user list into the report categories
$expTomorrow = $users | where {$_.passwordLastSet -le $tomorrow} | 
    sort -Property passwordlastset -Descending |select -property `
        @{Name="LogonName";Expression={$_.SamAccountName}}, 
        @{Name="PasswordExpiration";Expression={$_.PasswordLastSet.AddDays(365).ToString("dd-MMM-yyyy")}}
$exp15Days = $users | where {$_.passwordLastSet -gt $tomorrow -and $_.passwordLastSet -le $15days} | 
    sort -Property passwordlastset -Descending | select -property `
        @{Name="LogonName";Expression={$_.SamAccountName}}, 
        @{Name="PasswordExpiration";Expression={$_.PasswordLastSet.AddDays(365).ToString("dd-MMM-yyyy")}}
$expOver15Days = $users | where {$_.passwordLastSet -gt $15days} | 
    sort -Property passwordlastset -Descending | select -property `
         @{Name="LogonName";Expression={$_.SamAccountName}}, 
         @{Name="PasswordExpiration";Expression={$_.PasswordLastSet.AddDays(365).ToString("dd-MMM-yyyy")}}

# assemble body
$preHTML = @'
...
'@
$postHTML = @'
...
'@

$body = $preHTML
$body  = [fragment1]
$body  = ...

# Send message
Send-MailMessage ...
  

Используя три набора пользователей для вашего отчета, вы можете проверить выходные данные каждого из них по отдельности, чтобы убедиться, что они выглядят правильно.

Для вашего тестирования выполните Convertto-HTML -fragment несколько примеров коллекции, оберните их в действительно простой заголовок HTML, выведите в файл и посмотрите, как они выглядят в браузере.

Как только это будет выглядеть хорошо, создайте кодовый блок, чтобы собрать все тело в $body переменную. Помните, что некоторые из этих пользовательских коллекций могут быть пустыми, поэтому вам нужно будет добавить $body , чтобы в пустой коллекции не было ошибок (очевидно, проверьте это).

Я согласен с комментарием не переносить тело в еще одну таблицу. Просто создайте простой абзац со стилем текста для вашего заголовка. Не <span> используйте теги, если вы на самом деле не стилизуете текст. Еще раз проверьте, как он отображается в браузере при выводе в виде простого HTML-файла.

Тогда ваш Send-MailMessage может быть в своем собственном кодовом блоке. Это позволяет намного легче увидеть, где что-то идет не так.