How to sign and encrypt a message using S/MIME in PowerShell - powershell

I am attempting to create a PowerShell script that will:
Build a message
Sign the message using my private S/MIME certificate
Encrypt the message using the S/MIME public cert of the recipient
Send the email that has been signed and encrypted
I have included the full script below but changed email addresses, cert names, etc.
The private cert has been imported onto the machine using Internet Explorer. It is then referenced within the directory C:\Users\xxx\AppData\Roaming\Microsoft\SystemCertificates\My\Certificates\
The problem is that when I send the email using the script it is being encrypted but not signed.
However, if I don't encrypt the message and instead include $SignedMessageBytes when building the memory stream (see first line in step 4 of script) the email is signed correctly when being sent. This would suggest that the message is being correctly signed before the encryption occurs.
For some reason the script won't include the signature when encrypting the message.
What must I do so that the signature is included when the message is encrypted?
$SMTPServer = "localhost"
$Recipient = "recipient#emailaddress.com"
$From = "sender#emailaddress.com"
$RecipientCertificatePath = "C:\recipient#emailaddress.com.cer"
$SignerCertificatePath = "C:\Users\xxx\AppData\Roaming\Microsoft\SystemCertificates\My\Certificates\xxxx"
Add-Type -assemblyName "System.Security"
$MailClient = New-Object System.Net.Mail.SmtpClient $SMTPServer
$Message = New-Object System.Net.Mail.MailMessage
$Message.To.Add($Recipient)
$Message.From = $From
$Body = $null
$File= get-item -Path "C:\CONTRL__9911837000009_4045399000008_20170704_ELE00207.TXT"
$Message.Subject = $File.Name
# STEP 1: Capture Message Body
$MIMEMessage = New-Object system.Text.StringBuilder
$MIMEMessage.AppendLine("MIME-Version: 1.0") | Out-Null
$MIMEMessage.AppendLine("Content-Type: multipart/mixed; boundary=unique-boundary-1") | Out-Null
$MIMEMessage.AppendLine() | Out-Null
$MIMEMessage.AppendLine("This is a multi-part message in MIME format.") | Out-Null
$MIMEMessage.AppendLine("--unique-boundary-1") | Out-Null
$MIMEMessage.AppendLine("Content-Type: text/plain") | Out-Null
$MIMEMessage.AppendLine("Content-Transfer-Encoding: 7Bit") | Out-Null
$MIMEMessage.AppendLine() | Out-Null
$MIMEMessage.AppendLine($Body) | Out-Null
$MIMEMessage.AppendLine() | Out-Null
$MIMEMessage.AppendLine("--unique-boundary-1") | Out-Null
$MIMEMessage.AppendLine("Content-Type: application/octet-stream; name="+ $file.Name) | Out-Null
$MIMEMessage.AppendLine("Content-Transfer-Encoding: base64") | Out-Null
$MIMEMessage.AppendLine("Content-Disposition: attachment; filename="+ $file.Name) | Out-Null
$MIMEMessage.AppendLine() | Out-Null
[Byte[]] $binaryData = [System.IO.File]::ReadAllBytes($File)
[string] $base64Value = [System.Convert]::ToBase64String($binaryData, 0, $binaryData.Length)
[int] $position = 0
while($position -lt $base64Value.Length)
{
[int] $chunkSize = 100
if (($base64Value.Length - ($position + $chunkSize)) -lt 0)
{
$chunkSize = $base64Value.Length - $position
}
$MIMEMessage.AppendLine($base64Value.Substring($position, $chunkSize)) | Out-Null
$MIMEMessage.AppendLine() | Out-Null
$position += $chunkSize;
}
$MIMEMessage.AppendLine("--unique-boundary-1--") | Out-Null
[Byte[]] $MessageBytes = [System.Text.Encoding]::ASCII.GetBytes($MIMEMessage.ToString())
# STEP 2: Sign
$ci = New-Object System.Security.Cryptography.Pkcs.ContentInfo(,$MessageBytes)
$signedCms = New-Object System.Security.Cryptography.Pkcs.SignedCms($ci)
$SignerCertificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($SignerCertificatePath)
$Signer = New-Object System.Security.Cryptography.Pkcs.CmsSigner( $SignerCertificate )
$timeAttribute = New-Object -TypeName System.Security.Cryptography.Pkcs.Pkcs9SigningTime
$null = $signer.SignedAttributes.Add($timeAttribute)
$sha2_oid = New-Object System.Security.Cryptography.Oid("2.16.840.1.101.3.4.2.1")
$Signer.DigestAlgorithm = $sha2_oid
Write-Host "-----------------------------------------------------"
Write-Host "Cert friendly name: " $Signer.Certificate.FriendlyName
Write-Host "Cert subject : " $Signer.Certificate.Subject
Write-Host "Cert thumbprint : " $Signer.Certificate.Thumbprint
Write-Host "Digest algorithm : " $Signer.DigestAlgorithm.FriendlyName
Write-Host "Sign Time : " $Signer.SignedAttributes.Values.SigningTime
$signedCms.ComputeSignature($Signer)
$SignedMessageBytes = $signedCms.Encode()
# STEP 3: Encrypt
$ContentInfo = New-Object System.Security.Cryptography.Pkcs.ContentInfo (,$SignedMessageBytes)
$CMSRecipient = New-Object System.Security.Cryptography.Pkcs.CmsRecipient $RecipientCertificatePath
$algo_id = New-Object System.Security.Cryptography.Pkcs.AlgorithmIdentifier("2.16.840.1.101.3.4.1.42")
$EnvelopedCMS = New-Object System.Security.Cryptography.Pkcs.EnvelopedCms( $ContentInfo , $algo_id )
$EnvelopedCMS.Encrypt($CMSRecipient)
Write-Host "Key length : " $EnvelopedCMS.ContentEncryptionAlgorithm.KeyLength
Write-Host "OID friendly name: " $EnvelopedCMS.ContentEncryptionAlgorithm.Oid.FriendlyName
Write-Host "OID value : " $EnvelopedCMS.ContentEncryptionAlgorithm.Oid.Value
Write-Host "Parameters : " $EnvelopedCMS.ContentEncryptionAlgorithm.Parameters
[Byte[]] $EncryptedBytes = $EnvelopedCMS.Encode()
# STEP 4: Create and send mail
$MemoryStream = New-Object System.IO.MemoryStream #(,$EncryptedBytes)
$AlternateView = New-Object System.Net.Mail.AlternateView($MemoryStream, "application/x-pkcs7-mime; smime-type=enveloped-data;name=smime.p7m")
$Message.AlternateViews.Add($AlternateView)
$MailClient.Send($Message)

Thanks for your groundwork.
I got it working by adding an additional mime layer:
# STEP 3: Encrypt
$OID = New-Object System.Security.Cryptography.Oid 2.16.840.1.101.3.4.1.42
$AId = New-Object System.Security.Cryptography.Pkcs.AlgorithmIdentifier ($OID, 256)
$SignatureBytes = $SignedCMS.Encode()
$MIMEMessage2 = New-Object system.Text.StringBuilder
$MIMEMessage2.AppendLine('Content-Type: application/pkcs7-mime; smime-type=enveloped-data;name=smime.p7m') | Out-Null
$MIMEMessage2.AppendLine('Content-Transfer-Encoding: base64') | Out-Null
$MIMEMessage2.AppendLine() | Out-Null
$MIMEMessage2.AppendLine([Convert]::ToBase64String($SignedMessageBytes)) | Out-Null
Byte[]] $BodyBytes = [System.Text.Encoding]::UTF8.GetBytes($MIMEMessage2.ToString())
ContentInfo = New-Object System.Security.Cryptography.Pkcs.ContentInfo (,$BodyBytes)
$CMSRecipient = New-Object System.Security.Cryptography.Pkcs.CmsRecipient $ChosenCertificate
$EnvelopedCMS = New-Object System.Security.Cryptography.Pkcs.EnvelopedCms( $ContentInfo, $AId)
$EnvelopedCMS.Encrypt($CMSRecipient)
[Byte[]] $EncryptedBytes = $EnvelopedCMS.Encode()
I'm not sure if the code above will work out of the box since my variable names may be different from yours.
The code above is only tested with Outlook2016.

Related

Generate list of new and modified files on an FTP server using WinSCP .NET assembly

I've a PowerShell script that detects when a new file is uploaded on a FTP server.
I want to include list of such files (it's possible that they have multiple files) to a mail.
I already have the part of the script for add it to the mail and send it (I think I've done this in right way), but I only need the name of the file and not on the full path.
FYI : I'm using the winscpnet.dll library.
Have you a idea how to do it?
This is the script :
param (
# Use Generate Session URL function to obtain a value for -sessionUrl parameter.
$sessionUrl = "xxxxxxx",
$remotePath = "xxxxxxx"
)
### SENDING MAIL FONCTION IF NEW FILE ###
Function SendMail-New
{
$EXPEDITEUR = "xxxxxxx"
$DESTINATAIRE = "xxxxxxx","xxxxxxx"
$SUJET = "xxxxxxx"
$SERVEUR_SMTP = "sxxxxxxx"
$CORPS_MAIL = "xxxxxxx"
#$PJ = ($added -Join "`n") # If attached file
#$attachment = New-Object System.Net.Mail.Attachment($PJ) # For attached file
$Mail_Message = New-Object System.Net.Mail.MailMessage # Creating mail object
$Mail_Message.From = $EXPEDITEUR
$Mail_Message.Subject = $SUJET
$Mail_Message.Body = $CORPS_MAIL
#$Mail_Message.Attachments.Add($PJ)
$Mail_Adresses = $Mail_Message.To
if ($DESTINATAIRE -is "System.Array") # If more than 1 adress
{
foreach ($Adr in $DESTINATAIRE) # Adding each mail adress
{
$Mail_Adress = New-Object System.Net.Mail.MailAddress $Adr
$Mail_Adresses.Add($Mail_Adress)
}
}
else
{
$Mail_Adress = New-Object System.Net.Mail.MailAddress $DESTINATAIRE
$Mail_Adresses.Add($Mail_Adress)
}
$SMTPClient = New-Object Net.Mail.SmtpClient($SERVEUR_SMTP, xxxxxxx) # SMTP server and port
$SMTPClient.EnableSsl = $false # If SSL his activated or not - import the certificate before ?
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("xxxxxxx", "xxxxxxx"); #ICI Login et password du compte mail
$SMTPClient.Send($Mail_Message) # Mail sending
}
### SENDING MAIL FONCTION IF DELETED FILE ###
Function SendMail-Deleted
{
$EXPEDITEUR = "xxxxxxx"
$DESTINATAIRE = "xxxxxxx","xxxxxxx"
$SUJET = "xxxxxxx"
$SERVEUR_SMTP = "xxxxxxx"
$CORPS_MAIL = "xxxxxxx"
#$PJ = 'c:\script\Rapport.txt' # If attached file
#$attachment = New-Object System.Net.Mail.Attachment($PJ) # For attached file
$Mail_Message = New-Object System.Net.Mail.MailMessage # Creating mail object
$Mail_Message.From = $EXPEDITEUR
$Mail_Message.Subject = $SUJET
$Mail_Message.Body = $CORPS_MAIL
#$Mail_Message.Attachments.Add($PJ)
$Mail_Adresses = $Mail_Message.To
if ($DESTINATAIRE -is "System.Array") # If more than 1 adress
{
foreach ($Adr in $DESTINATAIRE) # Adding each mail adress
{
$Mail_Adress = New-Object System.Net.Mail.MailAddress $Adr
$Mail_Adresses.Add($Mail_Adress)
}
}
else
{
$Mail_Adress = New-Object System.Net.Mail.MailAddress $DESTINATAIRE
$Mail_Adresses.Add($Mail_Adress)
}
$SMTPClient = New-Object Net.Mail.SmtpClient($SERVEUR_SMTP, xxxxxxx) # SMTP server and port
$SMTPClient.EnableSsl = $false # If SSL his activated or not - import the certificate before ?
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("xxxxxxx", "xxxxxxx"); #ICI Login et password du compte mail
$SMTPClient.Send($Mail_Message) # Mail sending
}
### SENDING MAIL FONCTION FOR A SCRIPT ERROR ###
Function SendMail-Error
{
$EXPEDITEUR = "xxxxxxx"
$DESTINATAIRE = "xxxxxxx"
$SUJET = "xxxxxxx"
$SERVEUR_SMTP = "xxxxxxx"
$CORPS_MAIL = "Le script c'est fermé suite à une erreur: $($_.Exception.Message)"
#$PJ = 'c:\script\Rapport.txt' # If attached file
#$attachment = New-Object System.Net.Mail.Attachment($PJ) # For attached file
$Mail_Message = New-Object System.Net.Mail.MailMessage # Creating mail object
$Mail_Message.From = $EXPEDITEUR
$Mail_Message.Subject = $SUJET
$Mail_Message.Body = $CORPS_MAIL
#$Mail_Message.Attachments.Add($PJ)
$Mail_Adresses = $Mail_Message.To
if ($DESTINATAIRE -is "System.Array") # If more than 1 adress
{
foreach ($Adr in $DESTINATAIRE) # Adding each mail adress
{
$Mail_Adress = New-Object System.Net.Mail.MailAddress $Adr
$Mail_Adresses.Add($Mail_Adress)
}
}
else
{
$Mail_Adress = New-Object System.Net.Mail.MailAddress $DESTINATAIRE
$Mail_Adresses.Add($Mail_Adress)
}
$SMTPClient = New-Object Net.Mail.SmtpClient($SERVEUR_SMTP, xxxxxxx) # SMTP server and port
$SMTPClient.EnableSsl = $false # If SSL his activated or not - import the certificate before ?
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("xxxxxxx", "xxxxxxx"); #ICI Login et password du compte mail
$SMTPClient.Send($Mail_Message) # Mail sending
}
try
{
# Load WinSCP .NET assembly
Add-Type -Path "WinSCPnet.dll"
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.ParseUrl($sessionUrl)
$session = New-Object WinSCP.Session
try
{
# Connect
$session.Open($sessionOptions)
$prevFiles = $Null;
while ($True)
{
# Collect file list
$files =
$session.EnumerateRemoteFiles(
$remotePath, "*.*", [WinSCP.EnumerationOptions]::AllDirectories) |
Select-Object -ExpandProperty FullName
if ($prevFiles -eq $Null)
{
# In the first round, just print number of files found
Write-Host "Found $($files.Count) files"
}
else
{
# Then look for differences against the previous list
$changes = Compare-Object -DifferenceObject $files -ReferenceObject $prevfiles
$added =
$changes |
Where-Object -FilterScript { $_.SideIndicator -eq "=>" } |
Select-Object -ExpandProperty InputObject
if ($added)
{
Write-Host "Added files:"
Write-Host ($added -Join "`n")
Write-Warning "xxxxxxx"
SendMail-New # Send notification by mail for NEW FILE
echo "Mail envoyé"
}
$removed =
$changes |
Where-Object -FilterScript { $_.SideIndicator -eq "<=" } |
Select-Object -ExpandProperty InputObject
if ($removed)
{
Write-Host "Removed files:"
Write-Host ($removed -Join "`n")
Write-Warning "Un rapport d'intervention a été supprimé"
SendMail-Deleted # Send notification by mail for DELETED FILE
echo "Mail envoyé"
}
}
$prevFiles = $files
Write-Host "Sleeping 10s..."
Start-Sleep -Seconds 10
}
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
}
catch
{
SendMail-Error
Write-Host "Error: $($_.Exception.Message)"
echo "Mail d'erreur envoyé"
exit 1
}
I assume you do not have any subfolders in your comparison. Otherwise your requirement would not make sense to me.
If that assumption is correct, just compare plain file names (Name) instead of full paths (FullName). And exclude subfolders ([WinSCP.EnumerationOptions]::None), to make it clear that the code does not support them anymore.
$files =
$session.EnumerateRemoteFiles(
$remotePath, "*.*", [WinSCP.EnumerationOptions]::None) |
Select-Object -ExpandProperty Name

Power Shell: If condition variable comparison not working

I have a piece of code comparing two values, and if the condition is satisfied it sends out an email. But it is not working, help is appreciated.
code:
$filesize = Get-ChildItem $filename | Select-Object Length | Format-Wide
$filesize
$num=1265
$num
if("$filesize" -gt "$num")
{
$SMTPServer = "10.20.19.94"
$SMTPPort = 25
$username = "vcenter#somosadc.com"
#Define the receiver of the report
$to = "jeevan.m2#hcl.com"
$subject = "VM Snapshot Report"
$body = "VM Snapshot Report"
$attachment = new-object Net.Mail.Attachment($filename)
$message = New-Object System.Net.Mail.MailMessage
$message.subject = $subject
$message.body = $body
$message.to.add($to)
$message.from = $username
$message.attachments.add($attachment)
$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSSL = $false
#$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtp.send($message)
write-host "Mail Sent"
}
output:
1262
1265
Mail Sent
Why is it sending email if $filesize=1262 is less than $num=1265. It is killing me.
Because you're not comparing two numbers, you're comparing two strings.
Remove the Format-Wide command from the first pipeline, and remove the quotes around the arguments in your if condition:
$filesize = Get-ChildItem $filename | Select-Object Length
$num = 1265
if($filesize.Length -gt $num) {
<# ... #>
}

Emailing a Hard Drive Disk Space Alert Using Powershell

I've been browsing the web trying to find a way if possible to email a low disk space alert from a Gmail account to a shared mail box using power shell but Im struggling with a query I've managed to piece together.
$EmailFrom = "FromEmail#Gmail.com"
$EmailTo = "ToEmail#Gmail.com"
$SMTPServer = "smtp.gmail.com"
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("Username", "Password");
$Computers = "Local Computer"
$Subject = "Disk Space Storage Report"
$Body = "This report was generated because the drive(s) listed below have less than $thresholdspace % free space. Drives above this threshold will not be listed."
[decimal]$thresholdspace = 50
$tableFragment = Get-WMIObject -ComputerName $computers Win32_LogicalDisk `
| select __SERVER, DriveType, VolumeName, Name, #{n='Size (Gb)' ;e={"{0:n2}" -f ($_.size/1gb)}},#{n='FreeSpace (Gb)';e={"{0:n2}" -f ($_.freespace/1gb)}}, #{n='PercentFree';e={"{0:n2}" -f ($_.freespace/$_.size*100)}} `
| Where-Object {$_.DriveType -eq 3} `
| ConvertTo-HTML -fragment
$regexsubject = $Body
$regex = [regex] '(?im)<td>'
if ($regex.IsMatch($regexsubject)) {$smtpclinet.send($fromemail, $EmailTo, $Subject, $Body)}
Script runs but nothing happens, any help would be fantastic!!!
My version would be longer because I'd have made a substitute for Send-MailMessage such that swapping between mine and Send-MailMessage is trivial.
This is one possible way of doing it. There are good uses for the Fragment parameter on ConvertTo-Html, but not much of a justification to do so here.
This is a script and expected to be a .ps1 file. Mandatory things I don't really want to hard-code beyond a default are set in the param block.
param(
[String[]]$ComputerName = $env:COMPUTERNAME,
[Decimal]$Theshold = 0.5,
[PSCredential]$Credential = (Get-Credential)
)
#
# Supporting functions
#
# This function acts in much the same way as Send-MailMessage.
function Send-SmtpMessage {
param(
[Parameter(Mandatory = $true, Position = 1)]
[String[]]$To,
[Parameter(Mandatory = $true, Position = 2)]
[String]$Subject,
[String]$Body,
[Switch]$BodyAsHtml,
[String]$SmtpServer = $PSEmailServer,
[Int32]$Port,
[Switch]$UseSSL,
[PSCredential]$Credential,
[Parameter(Mandatory = $true)]
[String]$From
)
if ([String]::IsNullOrEmtpy($_)) {
# I'd use $pscmdlet.ThrowTerminatingError for this normally
throw 'A value must be provided for SmtpServer'
}
# Create a mail message
$mailMessage = New-Object System.Net.Mail.MailMessage
# Email address formatting si validated by this, allowing failure to kill the command
try {
foreach ($recipient in $To) {
$mailMessage.To.Add($To)
}
$mailMessage.From = $From
} catch {
$pscmdlet.ThrowTerminatingError($_)
}
$mailMessage.Subject = $Subject
$mailMessage.Body = $Body
if ($BodyAsHtml) {
$mailMessage.IsBodyHtml = $true
}
try {
$smtpClient = New-Object System.Net.Mail.SmtpClient($SmtpServer, $Port)
if ($UseSSL) {
$smtpClient.EnableSsl = $true
}
if ($psboundparameters.ContainsKey('Credential')) {
$smtpClient.Credentials = $Credential.GetNetworkCredential()
}
$smtpClient.Send($mailMessage)
} catch {
# Return errors as non-terminating
Write-Error -ErrorRecord $_
}
}
#
# Main
#
# This is inserted before the table generated by the script
$PreContent = 'This report was generated because the drive(s) listed below have less than {0} free space. Drives above this threshold will not be listed.' -f ('{0:P2}' -f $Threshold)
# This is a result counter, it'll be incremented for each result which passes the threshold
$i = 0
# Generate the message body. There's not as much error control around WMI as I'd normally like.
$Body = Get-WmiObject Win32_LogicalDisk -Filter 'DriveType=3' -ComputerName $ComputerName | ForEach-Object {
# PSCustomObject requires PS 3 or greater.
# Using Math.Round below means we can still perform numeric comparisons
# Percent free remains as a decimal until the end. Programs like Excel expect percentages as a decimal (0 to 1).
[PSCustomObject]#{
ComputerName = $_.__SERVER
DriveType = $_.DriveType
VolumeName = $_.VolumeName
Name = $_.Name
'Size (GB)' = [Math]::Round(($_.Size / 1GB), 2)
'FreeSpace (GB)' = [Math]::Round(($_.FreeSpace / 1GB), 2)
PercentFree = [Math]::Round(($_.FreeSpace / $_.Size), 2)
}
} | Where-Object {
if ($_.PercentFree -lt $Threshold) {
$true
$i++
}
} | ForEach-Object {
# Make Percentage friendly. P2 adds % for us.
$_.PercentFree = '{0:P2}' -f $_.PercentFree
$_
} | ConvertTo-Html -PreContent $PreContent | Out-String
# If there's one or more warning to send.
if ($i -gt 0) {
$params = #{
To = "ToEmail#Gmail.com"
From = "FromEmail#Gmail.com"
Subject = "Disk Space Storage Report"
Body = $Body
SmtpServer = "smtp.gmail.com"
Port = 587
UseSsl = $true
Credential = $Credential
}
Send-SmtpMessage #params
}

Powershell Email format and retrieving CN from Certificate subject

I'm trying to create a powershell script that will alert me when one or more of my certificates are about to expire.I combined some scripts i found on internet and it seems to work fine. The only problem is when sending the email im getting just one big row with all certificate one behind the other. I'd preffer to get more of a list like:
Certificate 1
Subject: CN =hello
Expiration:2/11/2017 1:00:00 AM
Certificate 2
Subject: CN =hello2
Expiration:2/11/2017 1:00:00 AM
If possible i would also like some help on how to just get the CN from the certificate subject rather the the complete subject with (OU, O, L, S,C)
Here is my current script:
import-module webadministration
$DaysToExpiration = 700 #just modify this date for more or less
$expirationDate = (Get-Date).AddDays($DaysToExpiration)
$body = Get-ChildItem CERT:LocalMachine/My |
Where {$_.NotAfter -lt (Get-Date).AddDays($DaysToExpiration)}
$body | select Subject, #{Name="Expiration"; Expression = {$_.NotAfter}} | fl | out-string
$emailSmtpServer = "172.17.1.236"
$emailSmtpServerPort = "25"
$emailSmtpUser = "test"
$emailSmtpPass = "test"
$emailMessage = New-Object System.Net.Mail.MailMessage
$PCName = $env:COMPUTERNAME
$emailMessage.From = "$PCName#test.com"
$emailMessage.To.Add( "test#dev.test.de" )
$emailMessage.Body = $body | select Subject, #{Name="Expiration"; Expression = {$_.NotAfter}} | fl | out-string
$emailMessage.Subject = "Certificates Expiring within $DaysToExpiration days"
$emailMessage.IsBodyHtml = $true
$SMTPClient = New-Object System.Net.Mail.SmtpClient( $emailSmtpServer , $emailSmtpServerPort )
$SMTPClient.EnableSsl = $false
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential( $emailSmtpUser , $emailSmtpPass );
if ($emailMessage.Body.Length -gt 1)
{
Write-host "Sending Email"
$SMTPClient.Send( $emailMessage )
}
I was searching for the same and I found the following stack overflow
link
$s = Get-ChildItem -Path 'Cert:\localmachine\My'| select subject
$s -replace "(CN=)(.*?),.*",'$2'
$s = $s -replace "#{Subject="
OR the non regex way ..
$sub = $_.Subject.split(",")[0].split("=")
$sub[1] = $sub[1] -replace "\*","star"
$sub[1]
It is working for most domain certificates but and I can see some issues with self certificates and server certificates.
Either configure $emailMessage.IsBodyHtml = $false or create an HTML body.

550 error on retrieving filesize while uploading file

I'm trying to get the file size while I'm uploading the file. My end goal is to try and get the upload speed, but in my while loop i get a Exception calling "OpenRead" with "1" argument(s): "The remote server returned an error: (550) File unavailable (e.g., file not found, no access).
Please see code below
$uploadRemoteFile = "Remote URI"
$ftpuname = "UserName"
$ftppassword = 'Password'
function upload-ftp{
$File = "$env:TEMP\something.exe"
$webclient = New-Object System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($ftpuname,$ftppassword);
$uri = New-Object System.Uri($uploadRemoteFile)
$webclient.UploadFileAsync($Uri, $File)
$arrayftp = #()
Function Get-newfilesize{
$webclientRead = New-Object System.Net.WebClient;
$webclientRead.Credentials = New-Object System.Net.NetworkCredential($ftpuname,$ftppassword);
[void]$webclientRead.OpenRead($uri);
[Int64]$bytes_total= ($webclientRead.ResponseHeaders["Content-Length"])
$webclientsize = ($bytes_total.ToString());
$webclientsize
}
while ($webclient.IsBusy){
$oldftpfile = Get-newfilesize;
$oldftpdate = Get-Date;
Start-Sleep -Milliseconds 1
$newftpfile = Get-newfilesize;
$newftpdate = Get-Date;
$ftpsizediff = $newftpfile - $oldftpfile;
$ftptimediff = $newftpdate - $oldftpdate;
$totalftpdiff = $ftpsizediff / $ftptimediff.totalseconds;
$totalftpdiff | foreach {
if ($_ -gt 0){$arrayftp += $_ }
}
}
$testftpcap= New-Object psobject -Property #{"Upload Speed" =((($arrayftp | measure -Average).Average/1MB)* 10)}
$testftpcap | Export-csv -NoTypeInformation -Path $env:TEMP\ftpspeed.csv
}
Thanks
Not exactly a direct answer to your question but you could use Powershell FTP module - works great and has a progress bar too..
(http://gallery.technet.microsoft.com/scriptcenter/PowerShell-FTP-Client-db6fe0cb)