ExtendedPropertyDefinition declaration for EmailMessage in Powershell throws exception - powershell

since I got to know that ExtendedProperties have its limit for a specific mailbox in the EWS cloud I am trying to switch up my code to have only one ExtendedProperty and just change its value each time I am assigning the property to an e-mail message I am sending to then find it and work on the e-mail message object later on in the program.
I am having a hard time setting this up correctly even though I am following the docs, but it just seems to not work out for me.
This is the code part that throws an Exception: "Multiple ambigious overloads found for "ExtendedPropertyDefinition" and the argument count "3" :
# email declaration exposing the $email object
.
.
.
# property declaration and setting the value
# since I want to have only one extended property, this is actually a valid GUID string that I then # convert to a Guid type
$GUIDproperty = "00000000-0000-0000-0000-000000000000"
$propertyGUID = [Guid]$GUIDproperty
# since I want to have a unique value each time set to the existing extended property
$propertyValue = [guid]::NewGuid().ToString()
$propertyName = "Id"
$ExtendedProperty = [Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition]::new($propertyGUID, $propertyName, $propertyType)
# well I dont even reach this part, but just for the big picture
$email.SetExtendedProperty($ExtendedProperty, $propertyValue)
The docs I have followed for that are the following:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.exchange.webservices.data.extendedpropertydefinition.-ctor?view=exchange-ews-api#microsoft-exchange-webservices-data-extendedpropertydefinition-ctor(microsoft-exchange-webservices-data-defaultextendedpropertyset-system-string-microsoft-exchange-webservices-data-mapipropertytype)
https://learn.microsoft.com/en-us/dotnet/api/microsoft.exchange.webservices.data.folder.setextendedproperty?redirectedfrom=MSDN&view=exchange-ews-api#Microsoft_Exchange_WebServices_Data_Folder_SetExtendedProperty_Microsoft_Exchange_WebServices_Data_ExtendedPropertyDefinition_System_Object_
https://learn.microsoft.com/en-us/dotnet/api/system.guid?view=net-7.0

The following works okay for me
$propertyType = [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::String
$GUIDproperty = "82e3d64f-e26d-4321-8fc3-c31aa790197c"
$propertyGUID = [Guid]$GUIDproperty
$propertyValue = [guid]::NewGuid().ToString()
$propertyName = "MyPropId"
$ExtendedProperty = [Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition]::new($propertyGUID, $propertyName, $propertyType)
return $ExtendedProperty
You don't specify what you using in the $propertyType so that maybe it, could also be to do with the versions you using. What version of PowerShell and the EWS Managed API are you trying ?

Related

Issue using Dotnetzip in powershell error consider setting UseZip64WhenSaving

I have used dotnetzip in c# with large files with no problem. I have a requirement to zip up some large files in the power shell. I see from dotnetzip docs I can use it iN ps .
But I keep getting the error
Compressed or Uncompressed size, or offset exceeds the maximum value. Consider setting the UseZip64WhenSaving property on the ZipFile instance.
this is my PS code. How do I set the UseZip64WhenSaving in PS?
[System.Reflection.Assembly]::LoadFrom("D:\\mybigfiles\\Ionic.Zip.dll");
$directoryToZip = "D:\\mybigfiles\\";
$zipfile = new-object Ionic.Zip.ZipFile;
#$zipfile.UseZip64WhenSaving;
$e= $zipfile.AddEntry("mybig.csv", "This is a zipfile created from within powershell.")
$e= $zipfile.AddDirectory($directoryToZip, "home")
$zipfile.Save("D:\\mybigfiles\\big.zip");
$zipfile.Dispose();
Working C# code.
using (ZipFile zip = new ZipFile())
{
zip.UseZip64WhenSaving = Zip64Option.AsNecessary;
zip.AddFile(compressedFileName);
zip.AddFile("\\\\server\\bigfile\\CM_Report_20220411200326.csv");
zip.AddFile("\\\\server\\bigfile\\PM_Report_20220411200326.csv");
zip.AddFile("\\\\server\\bigfile\\SCE_Report_20220411200326.csv");
}```
Unlike C#, PowerShell loves implicit type conversions - and it'll implicitly parse and convert a string value to its cognate enum value when you assign it to an enum-typed property:
$zipfile.UseZip64WhenSaving = 'AsNecessary'
Alternatively, make sure you qualify the enum type name:
#$zipfile.UseZip64WhenSaving = [Ionic.Zip.Zip64Option]::AsNecessary
It's also worth noting that all PowerShell string literals act like verbatim strings in C# - in other words, \ is not a special character that needs to be escaped:
$directoryToZip = "D:\mybigfiles\"
# ...
$e = $zipfile.AddDirectory($directoryToZip, "home")
$zipfile.Save("D:\mybigfiles\big.zip")

BizTalk Orch/SMTP - Microsoft.XLANGs.BaseType.Content must be a message property of

This is related to my question from 2017: How Set Attachment Name to Show Properly in Outlook
This time, I have an orchestration with the following in a construct shape:
attachmentName = System.IO.Path.GetFileName(
msg_Ledger6002_File_XmlDoc
(FILE.ReceivedFileName));
msg_Email.BodyPart = new ABC.Ledger6002.Component.RawString("See attached email.");
msg_Email.AttachmentPart = msg_Ledger6002_File_XmlDoc;
// attachmentName is set earlier in orch so we could write it to EventLog for debugging
msg_Email.AttachmentPart(MIME.FileName) = attachmentName;
//msg_Email.AttachmentPart(MIME.ContentDescription) = "body";
//msg_Email.AttachmentPart(MIME.ContentTransferEncoding) = "base64";
// These are working
msg_Email(SMTP.Subject) = "Ledger6002 File";
msg_Email(SMTP.SMTPTo) = msg_Config_Email.smtpToEmail;
msg_Email(SMTP.From) = msg_Config_Email.smtpFromEmail;
msg_Email(SMTP.SMTPAuthenticate) = 0; // do not authenticate to SMTP server
// trying these two new parms below
msg_Email(SMTP.EmailBodyTextCharset) = "UTF-8";
msg_Email(Microsoft.XLANGs.BaseTypes.ContentType) = "text/plain";
The last line above gives me an expression shape not valid, and when I mouse over it it says identifies the error as:
Microsoft.XLANGs.BaseType.Content must be a message property of
msg_email.
Before I added the two lines under the comment "trying these two new parms below", I am getting an email with the desired attachment. The problem is that it is just called "body" and when I do "save as" from Outlook, it wants to call it "body" instead of the name of the file I dropped.
I'm using a "specify later" statically configured SendPort with PassThru for the Pipeline. I have tried a pipeline with MimeEncoder, but that caused the attachment to appear in the body. I would like to move to a dynamic pipeline, but so far I've got the static one working except for the name assigned to the file attachment.
To fix the error: "Microsoft.XLANGs.BaseType.Content must be a message property of msg_email.", I just needed to include the part name (the message is associated with a multipart message type, and I didn't include the partname):
Wrong:
msg_Email(Microsoft.XLANGs.BaseTypes.ContentType) = "text/plain";
Right:
msg_Email.BodyPart (Microsoft.XLANGs.BaseTypes.ContentType) = "text/plain";
I'm still working on getting the email with attachment to come out correctly, but so far this post https://social.msdn.microsoft.com/Forums/en-US/988b0d91-1e5a-4f73-b30d-417d6ea9fa75/attachment-name-in-outlook-is-ok-see-on-exchange-always-named-body?forum=biztalkgeneral seems to be the best explanation.

ToRecipients Will Not UpdateEWS Managed API 2.2

According to MSDN
I am trying to update ToRecipients property is writable.
When I run the following code in Powershell:
foreach ( $Item in $SearchResults ) {
Write-Output $item.Subject
$Item.Load()
$Item.Sender.Name = 'TS'
$item.IsRead = $false
$item.Subject = 'Test'
$item.ToRecipients.Name = 'DisplayName Three'
$Item.Update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite)
}
It would Save subject, however neither Sender or ToRecipients get updated.
Could someone please advise what I am doing wrong?
Thank you
According to MSDN I am trying to update ToRecipients property is writable
No that property is ReadOnly according to the documentation eg
That property is just a cacluated property based on the contents of the Recipients collection which I believe is also ReadOnly on a Message once its been received in EWS.

Search a Lotus Notes database from PowerShell

I am trying to search a Lotus Notes database from PowerShell and getting a "Type Mismatch. (Exception from HResult: 0x80020005 (DISP_E_TYPEMISMATCH)" At line 1: char:1.
Set-up code:
$notesSession = New-Object -ComObject Lotus.NotesSession
$notesSession.Initialize()
$notesDb = $notesSession.GetDatabase(..., ...)
I get the errors when trying...
$results = $notesDb.Search("text", $null, 0)
$results = $notesDb.Search("text", $(Get-Date), 0)
$results = $notesDb.Search("text", $([System.DateTime]::Now), 0)
Can anybody spot the mistake? I think the error is to do with the date argument, hence my multiple attempts.
The error seems to be coming from the fact that .Search wants a notesDateTime object for that parameter. So in theory you just need to create a notesdatetime object and pass that to the search method.
$searchDate = $notesSession.CreateDateTime(get-date -f "yyyy-MM-dd")
I am not in a position to test this nor am I sure how to get a null return from this short of passing $null to the CreateDateTime method.
Unsure if this is the correct reference for the COM implementation but from the parameter section
The date and time you want the object to represent. If you use an empty string (""), the date is set to a wildcard date. The Notes date-time expressions "Today," "Tomorrow" and "Yesterday" are supported.

Dynamically pass parameters to DSC resource?

I was working on a composite resource when I came across the issue of being able to dynamically pass parameters to a DSC resource and wondered if there's another way to tackle this that I'm missing.
Basically, I have the an array (Below) that contains one PSObject per desired file-share. Each of these PSObjects has properties that are used as parameters for my DSC resource (In this case the cLocalFileShare community resource).
The issue is, not all of these objects have all of the parameters defined. For example, some of my shares don't have any users/groups assigned to the ReadAccess permission, but in my ForEach loop (Below), a $null value is being passed to the actual resource as this permissions isn't defined, and this causes the resource to error as it is trying to set ReadAccess permissions to user $null.
My issue is, how do I tackle this - for this resource and others?
I've tried splatting the parameters in the DSC resource, but this doesn't seem to be supported. If this worked, I could build a different parameter list and pass that.
Somebody on Reddit suggested passing a string that contained all of the parameters, but again this doesn't seem to be supported.
My worst fear is, I will have to edit each resource to support (and ultimately ignore) $null values which seems like a really bad way to tackle this.
So, here's my array containing a PSObject per file share.
$MyConfig = #(
#{
Path = 'D:\Shares\Accounting'
Name = 'Accounting'
Ensure = 'Present'
ChangeAccess = 'AccountingAdmins'
ReadAccess = 'AccountingInterns,FinanceDepartment'
}
#{
Path = 'D:\Shares\Software'
Name = 'Software$'
Ensure = 'Present'
ReadAccess = 'DomainUsers'
}
)
Now, within the actual DSC configuration...
configuration {
ForEach ($ShareProperties in $MyConfig) {
# Each resource is named after the Path specified, but with the colon replaced as that's not valid character for the resource name
cLocalFileShare $ShareProperties.Path.Replace(':','__') {
Path = $ShareProperties.Path
Name = $ShareProperties.Name
Ensure = $ShareProperties.Ensure
ChangeAccess = $ShareProperties.ChangeAccess
ReadAccess = $ShareProperties.ReadAccess
}
}
}
Not the most elegant solution. But you could use a conditional section within your ForEach loop.
configuration {
ForEach ($ShareProperties in $MyConfig) {
# Each resource is named after the Path specified, but with the colon replaced as that's not valid character for the resource name
if ($ShareProperties.ChangeAccess -eq $null) {
cLocalFileShare $ShareProperties.Path.Replace(':','__') {
Path = $ShareProperties.Path
Name = $ShareProperties.Name
Ensure = $ShareProperties.Ensure
ReadAccess = $ShareProperties.ReadAccess
}
}
else
{
cLocalFileShare $ShareProperties.Path.Replace(':','__') {
Path = $ShareProperties.Path
Name = $ShareProperties.Name
Ensure = $ShareProperties.Ensure
ChangeAccess = $ShareProperties.ChangeAccess
ReadAccess = $ShareProperties.ReadAccess
}
}
}
}