How to send email by using MailKit via PowerShell? - powershell

I am having difficulty creating the Message object using mailkit so I can add the From, To, Subject and body with message that may have attachments to be send before disconnecting. I have created the MailKit object, Cancelation Token object. I am able to load the MailKit and MimeKit dlls using the add-type -path and I am able to connect, authenticate, Disconnect and Dispose but the message object creation part and sending is where I need help with. I have the following:
$MkSmtp = New-Object MailKit.Net.smtp.SmtpClient
$CanToken = New-Object System.Threading.CancellationToken ($false)
$SSL = [MailKit.Security.SecureSocketOptions]::SslOnConnect
$MkSmtp.Connect($MailServer, $Port, $SSL, $CanToken)
$MkSmtp.Authenticate(([System.Text.Encoding]::UTF8), $Username, $Password, $CanToken)
#$Message = New-Object ????
$MkSmtp.Send($Message)
$MkSmtp.Disconnect($true)
$MKSmtp.Dispose()
I thought the answer was:
$Message = [Mimekit.MimeMessage]::new()
$Message.From.Add($From)
$Message.To.Add($To)
$Message.Subject = "Test"
$TextPart = [MimeKit.TextPart]::new("plain")
$Body = "This is just a test"
$TextPart.Text = $Body
$Message.Body = $TextPart
Which came from https://www.powershellgallery.com/packages/PSGSuite/2.13.2/Content/Private%5CNew-MimeMessage.ps1. This worked on my developer machine but putting it to production yields the following error:
Method invocation failed because [MimeKit.MimeMessage] does not contain a method named 'new'
When it tries to go passed the following line:
$Message = [Mimekit.MimeMessage]::new()
Placing a breakpoint at this line after loading the dll via add-type and running "[MimeKit.MimeMessage] | Get-Member -Static" on the powershell command line on the development and production server it shows the following:
Development
Production
Same DLL is loaded on both the Development and Production. I have loaded the DLL using both Add-Type and System.Reflection.Assembly. Production is on PowerShell 4.0 while my development box is on PowerShell 5.1. Don't know if that is the issue. Anyone have any ideas?

Updated our live server to WIndows Management Framework 5.1 (PowerShell) and now has the New Method when viewing the Static Get-Member.

$Message = New-Object Mimekit.MimeMessage

Related

Powershell script unable to decrypt password from Jenkins withCredentials()

I created a powershell script to run DB2 queries in Jenkins
withCredentials([usernamePassword(credentialsId: 'cred-id', usernameVariable: 'ID', passwordVariable: 'PASSWORD')]) {
$cn = new-object system.data.OleDb.OleDbConnection("Server=Server; Provider=IBMDADB2;DSN=DBName;User Id=$ID;Password=$PASSWORD");
$ds = new-object "System.Data.DataSet" "ds"
$q = "myQuery"
$da = new-object "System.Data.OleDb.OleDbDataAdapter" ($q, $cn)
$da.Fill($ds)
$cn.close()
}
If I run the script and hard code my credentials, it run fine.
With withCredentials(), I am getting the following error: Security processing failed with reason "15" ("PROCESSING FAILURE")
From some research, the error seems to be because DB2 can't handle encrypted data. Is there a way to overcome this error?
EDIT:
I tried to add
$SecurePassword = ConvertTo-SecureString $PASSWORD -AsPlainText -Force
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword)
$UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
at the beginning of my powershell script, but it still throws the same error even though the credential work fine if used in plain text
If I understand the docs for the Credentials Binding Jenkins plugin correctly, the variables designated in the withCredentials() call become environment variables, so as to enable their use across process boundaries.
Note that the values of these environment variables are not encrypted, so no extra (decryption) effort is required on the part of the target process.
Therefore, you need to use $env:[1] instead of just $ to refer to these variables in PowerShell:
$cn = new-object system.data.OleDb.OleDbConnection "Server=Server; Provider=IBMDADB2;DSN=DBName;User Id=$env:ID;Password=$env:PASSWORD"
[1] See the conceptual about_Environment_Variables help topic.

Create New Outlook 365 Email in PowerShell

I'm trying to create an Outlook email in PowerShell, and I've found the same code everywhere to do it:
$ol = New-Object -comObject Outlook.Application
$mail = $ol.CreateItem(0)
$mail.Subject = "<Subject>"
$mail.Body = "<Body>"
and then either
$inspector = $mail.GetInspector
$inspector.Display()
Or
$mail.Display()
to show the email.
However, at the very first line I get this error:
New-Object : Retrieving the COM class factory for component with CLSID {0006F03A-0000-0000-C000-000000000046} failed due to the following error: 80080005 Server execution failed (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)).
I've tried it without the -comObject and get a different error:
New-Object : Cannot find type [Outlook.Application]: verify that the assembly containing this type is loaded.
I've tried loading the assembly with
[Reflection.Assembly]::LoadWithPartialname("Microsoft.Office.Interop.Outlook") | out-null
but still get the same error messages when running the previous commands.
In case it matters, we are using Office 365, but I do have a local copy of Office installed. Is there a different type of object I need to use with Office 365?
Also, it looks like it's trying to reach out to a server to create the object. Is there a way for me to force it to do so locally?
CO_E_SERVER_EXEC_FAILURE means Outlook is running in a security context different from that of your app. COM system refuses to marshal calls between processes running in different security contexts.

Attaching build configuration to template via API [TeamCity]

I'm trying to attach a build configuration to a template. We're running TeamCity 10.0.2, using PowerShell 4.0 to interact with it.
According to the TeamCity 10 API documentation, the attachment of builds to templates operation is possible:
Read, detach and attach a build configuration from/to a template:
GET/DELETE/PUT
http://teamcity:8111/app/rest/buildTypes//template
(PUT accepts template locator with the "text/plain" Content-Type)
So I'm trying to attach the build12 build configuration to the template12 template, the code I'm doing this with is as follows
$webclient = New-Object System.Net.WebClient
$creds = New-Object System.Net.NetworkCredential("user1","pass1")
$webclient.Credentials = $creds
$webclient.headers.Add("Content-Type", "text/plain")
$webclient.UploadString("http://teamcity:8111/httpAuth/app/rest/buildTypes/build12/template", "PUT", "TemplateId")
But I keep getting the following error back:
Exception calling "UploadString" with "3" argument(s): "The remote server returned an error: (400) Bad Request."
Has anyone been able to attach build configurations to templates through the API?
I see you using PowerShell, but you're dropping down the the C# WebClient class to do it. Don't do that :)
Invoke-RestMethod http://teamcity/httpAuth/app/rest/buildTypes/YourBuildId/template -Credential $credential -Method Put -Headers #{"Content-Type"="text/plain"} -Body Your_Template
This will attach the template Your_Template to your build called YourBuildId
If you need help with the -Credentials param or anything else, let me know.
I've actually got it to work using the above...

How to run powershell script using default credential from sql job agent

I am downloading a file from sharepoint.
I have already scheduled the job in SQL job agent
Its working fine when i use the following code
$UserName = "xxxx"
$PswdPath = "D:\securestring.txt"
$SecurePassword = cat $PswdPath| convertto-securestring
$fileName = [System.IO.Path]::GetFileName($FileUrl)
$DownloadPath = "D:\Excel\"
$downloadFilePath = [System.IO.Path]::Combine($DownloadPath,$fileName)
$client = New-Object System.Net.WebClient
$client.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $SecurePassword)
$client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f")
$client.DownloadFile($FileUrl, $downloadFilePath)
$client.Dispose()
But the problem here i face is whenever i update my password i need to update the secure string as well
So i wanted to use the default credentials
so i used the following script
$webclient = New-Object System.Net.WebClient
$webclient.UseDefaultCredentials = $true
$webclient.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f")
$webclient.DownloadFile($FileUrl, $DownloadPath)
but its getting failed with the following error
Exception calling "DownloadFile" with "2" argument(s): "The remote server returned an error: (401) Unauthorized."
went through different blogs all were suggesting the same approach which i have followed
Any help in this regard?
As far as I understand default credentials users the account and password the sql agent process is started and since it will not match the SharePoint online account it will fail. It would be easier if you create a powershell that updates all secure strings once password is changed.

access sharepoint REST api using powershell with windows authentication

I have a sharepoint 2013 server, which I can log into using Windows Authentication via a web-browser. When I have logged on using my browser, if I then - using that same browser - browse to http://mysharepointserver/_api/web I get some useful XML.
However, I want to write a powershell script that uses this XML. To that end, following the suggestions from this page:
How to make an authenticated web request in Powershell?
I wrote the following code:
$PWord = ConvertTo-SecureString –String "MyAwesomePassword" –AsPlainText -Force
$creds = New-Object System.Net.NetworkCredential("MyUserName",$PWord,"TheDomain")
$webclient = New-Object System.Net.WebClient
$webclient.Credentials = $creds
$url = "http://mysharepointserver/_api/web"
$output = $webclient.DownloadString($url)
echo $output
However, when I run this code, I get the error message:
Exception calling "DownloadString" with "1" argument(s): "The remote server returned an error: (403) Forbidden."
Even though I can access the same URL using a web-browser, if I type in the (same) credentials using the Windows login dialog that pops up for authentication purposes.
Does anyone know if it is possible to do this using Powershell?
thanks heaps all
Why aren't you using the default CMDlets that come with Powershell (unless using PS2 or lower)?
Invoke-Webrequest and Invoke-Restmethod both support the -credential switch which can be used to authenticate against the webserver.
You can also use Get-credential to store your credentials (though you can't get yhem from a file or string that way, at least not the password)
Script (in pseudo code and since i'm on my phone no code tags) would look like this :
Invoke-Restmethod -uri 'http://bla/api' -credential (get-credential)