Closed nate-kis closed 2 years ago
I'll try to look into this after next week because next week I'm on skiing holiday
Hi would also be highly interested in removing the System.Drawing depedency since I want to use the reader in an Azure Function and there it is not supported.
Will maybe try myself to replace System.Drawing with ImageSharp in a seperate branch, since there are little references. Are pull requests supported? https://stackoverflow.com/questions/51904125/azure-function-gives-error-system-drawing-is-not-supported-on-this-platform
Also very interested in a .NET6 target, since this way the dependencies to .NET Standard don't have to be deployed with .NET 6.
I'm always open for pull requests.
So I made a quick attept to port the library to ImageSharp (Apache Licence)
https://github.com/MichaelPeter/MSGReader/commit/f66a85b315c27de6345a9cc0c8aacc5eb4c1b131
Essentially System.Drawing is barely used, BUT at a few key places.
The Loading and Saving of PNGs I could be quickly replace with ImageSharp,
but two things would need to be solved:
In the Document class SystemFonts.Default Font - if used for generating html this could be maybe replaced with nothing or null. But here I lack knowolege of the sourcecode?
And the acutally difficult problem: For Inline RTFs the pictures are saved as .ico files and ImageSharp does not support .ico since it is a microsoft format.
I did not find a library yet to extract files from Icons yet without using the winApi yet.
EDIT Regarding Icon Support:
TL;DR: FreeImage-dotnet-core or with ImageMagick.NET seemed the most interesting to me event if no commits since 2017, but ico is also not changing.
Soooo
Here is btw the article from Microsoft where they recommend switching to ImageSharp, Skia or Maui Graphics https://docs.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/6.0/system-drawing-common-windows-only#recommended-action
Maui Graphics: Only .NET6 but have ico support - maybe starting with .NET6? https://github.com/dotnet/Microsoft.Maui.Graphics/blob/0e9a4cdadbc077cc29103c0a12a5b24b5beb6e7e/src/Microsoft.Maui.Graphics.SharpDX.Shared/D2BitmapExtensions.cs#L101
ImageSharp: No support for ico but pure .NET: https://github.com/SixLabors/ImageSharp/discussions/1315
SkiaSharp - seems to support Ico but probably overkill.
This post was very intersting https://stackoverflow.com/a/44428480
CoreCompat: Autor recommends to move to now also obosolete System.Drawing.Common https://stackoverflow.com/a/47208937/3181933
Image Magick: Supports extracting icos but kind of huge overhead. https://github.com/dlemstra/Magick.NET/blob/46a352cdb431935f35af59b8125fa45f1c50a1a9/src/Magick.NET/Optimizers/IcoOptimizer.cs#L224
Using FreeImage-dotnet-core directly: The wrapper is last updated 2017, but ico also doesn't change anymore: Since image magick uses this package for images we could also use it directly: https://github.com/matgr1/FreeImage-dotnet-core/blob/f9ede8251be907ebf3c469995fe1c6a0f7ccb534/src/Samples/Sample%2001%20-%20Loading%20and%20saving/Program.cs#L104
Using libgdiplus directly Possible for this purposes, but microsoft dropped support because makers didn't respond anymore.
At the moment I'm busy with porting another project to .NET 6, when this is done I'll start with MSGReader
hi, @Sicos1977 any progress on this issue?
So the issue with linux/net6 support is actually just the SystemFont.DefaultFont for fnil. If the call is replaced with string empty it works.
Even if it is not clean replacing it with string empty
The part with the ImageLibrary is actually just used if Messages are written.
I was not yet deep enough in the code to make a proper fix
Hi @MichaelPeter,
I fixed the issue by assigning arial to FNIL as below,
case "fnil":
name = "Arial"; // SystemFonts.DefaultFont.Name;
nilFlag = true;
break;
Thx for hint
@SteAmeR : Not yet but I'm finished with porting the other project so I'll try to pick this one up next week.
name = "Arial"; // SystemFonts.DefaultFont.Name;
Used your solution when compiled for .net5 or 6 --> 20295b97bf82adef8f360acb3bcc269396ad9dec
Yes I used for .net6. Also test on linux and worked it :)
I check microsoft but var icon = Icon.ExtractAssociatedIcon(fileInfo.FullName)
should work on .net 6
So no need for a replacement
Added support for .net 5 and 6 (also on Linux) --> https://github.com/Sicos1977/MSGReader/releases/tag/4.4
You can get a new package from nuget
Describe the bug .MSG files are not able to be read/parsed on .NET 6 when the code is running on linux.
One of the .NET 6 breaking changes is that it now no longer supports the system.drawing.common on linux. (see .net 6 breaking change here)
The exception you get is:
Error Message: System.TypeInitializationException : The type initializer for 'Gdip' threw an exception. ---- System.PlatformNotSupportedException : System.Drawing.Common is not supported on non-Windows platforms. See https://aka.ms/systemdrawingnonwindows for more information. Stack Trace: at System.Drawing.SafeNativeMethods.Gdip.GdipGetGenericFontFamilySansSerif(IntPtr& fontfamily)
For .NET 5, you are able to install the linux package libgdiplus to have it work, but this no longer is a workaround.
To Reproduce Steps to reproduce the behavior:
- Try processing a .msg email in a .NET 6 application on linux
Expected behavior The .msg email will be able to be parsed.
Desktop (please complete the following information):
- OS: Linux
- .NET 6
I replaced system.drawing.commen with microsoft.maui.graphics .. it is still a preview version but works for me without any problems.... and you probably won't need it that much anyway.
Yay thanks for fixing!!!
What would also be really awsome, if the .NET 6 support would allow at least reading of mails in WebAssembly / under Blazor.
Since the whole library and its dependencies are C# this way the mails could be parsed on Client side in the Browser. This way even a client side webpage could be build, which extracts the mail data and renders it into a sandboxed IFrame (security concerns ignored for now) without any calls to the server side or any server side performance or security issues.
EDIT: Or should I create a seperate issue for WebAssembly support?
If Maui works that is really nice. Not sure if it is also based on on Skia, but skia also works in the browser. But writing mails in the browser is right now not so interesting.
At the moment I'm not going to add support for webassembly, never did anything with that and I don't feel anything for it to invest time in it because most of the times this library is used on a server.
But feel free to add support yourself and sent me a pull request ;-)
Thanks for the offer :) I will at least check it out in a POC and tell about the roadblocks.
Will not overpromise on pull requests, but lets see ;-)
So Update regarding Blazor/Webassembly: I tried it in a Poc interestingly reading EML and MSG works so far without problems!
Meaby it has something todo with making it C# .NET 6 compatible.
Well sadly it is not that easy. Blazor Webassembly can also run .NET Standard Code or .NET5 code.
Principally Blazor/Webassembly can run any .NET Code (Keyword One-Dotnet) but if certain features are used, like here the windows api interop call, it will fail during runtime since in the browser you cannot access the windows API. Like for SystemFonts the GDI+ call to GdipGetGenericFontFamilySansSerif) fails.
But it is is not immediately obvious that System.Drawing relies still heavily on operating system functions (GDI+).
Microsoft is starting to introduce [UnsupportedOSPlatform("browser")] or [SupportedOSPlatform("browser")] Attribute so it can fail during compile time, but this is not yet consistent. https://docs.microsoft.com/en-us/dotnet/standard/analyzers/platform-compat-analyzer
The calls to write Mails will logically also fail, since there you create temporary files - but latter is logically not possible in the browser. Or things like the C# SMTP Send will fail, since there is no access to the TCP/IP layer in the browser.
Also there are more less obvious apis. Like many C# Cryptography APIs don't work in the browser, since in the OS they are hardware accelerated and provided by the OS.
Btw in writing mails, have you considered writing the images as base64 instead of linking external files? Like here stackoverflow.com/a/8499716/10019244
<img src="data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />
But since we removed SystemFronts, reading works very well :D And thankfully your dependenies RtfPipe
and openmcdf
are pure C# and don't rely somewhere on a windows interop call or simular! 👍
Just curious, what is your use case with MSGReader? Ofcourse reading MSG files but in what context?
My personal projects is writing a document management system - optionally cloud hosted - in the browser. When I click on a document I want a live preview. For PDFs there is PDF.js, but especially .MSG Documents are more difficult to display in browser, since they use this propretary microsoft format.
My first idea was extracting the Html in an AWS Lambda or Azure Function. Second idea was rendering a PDF of the mail on the server. But both idea adds costs since I either need to render a pdf every time a user views a document or store the cached rendition or extracted html somewhere.
But if MsgReader runs directly in the browser, I can just download the .MSG or .EML document and then display the extracted html directly in an sandboxed Iframe, without processing costs on the server. There is a security risk, in case of tracking pixels in the mails and that I render any HTML in the users browser, but even microsoft sharepoint does it that way.
Google had libraries to display mail html savely, but in best google fashion the projects got abandoned.
I send you a personal mail if you are more interested :)
@Sicos1977 Thank you for making MSGReader works on Linux. But why does it still refrence System.Drawing.Common v7 even after migrating to Maui? Is it possible to git red of it inteirely since it doesn't work on Linux?
Could be a left over from the past. Have to check if it is still needed and if not I will remove it. Thanks for mentioning.
Thank you. I had a quick look and foun that it's used only in Windows for Imaging. but there is other code that's used for Linux. If the Linux code can run on Windows or if there is a cross platform alternative it will be very nice to remove System.Drawing.Common. Or at least downgrade it to v6, because v7 doesn't work on Linux.
I just checked the code and I made it in such a way the it is only used when the code is run on Windows. When the code is run on Linux it uses MUAI
I see. But because the Nuget references System.Drawing.Common v7, it forces projects that uses it to upgrade to this version which isn't supported on Linux. i.e. one can't use MSGReader and System.Drawing.Common v6 (the latest version supported on Linux). Is it possible to get rid of Ssytem.Drawing.Common entirely and use MUAI on both Windows and Linux? or atleast downgrade to System.Drawing.Common v6? Thank you for your prompt response.
I didn't know that this exists as a side effect of this choice. I'll downgrade the version back to 6. Also MUAI does not work in the .NET framework that is why I did have to make this choice.
I changed the visual studio project file so that it only uses System.Drawing.Comment when the .net462 framework is used
This should get rid of the problem on Linux since the .net framework does not work overthere and you at least need .net 5 or 6 and that one uses MUAI. Also changed the code so different assemblies are build on different .net versions
If there is still an issue than please open a new issue instead of reusing this one. I always get lost in issues that are already closed.
I just published version 5.4.0 that should get rid of the System.Drawing.Common problem on Linux because it is now only tied to the .NET 4.6.2 framework that only works on Windows
Wonderful! Thank you very much for implementing this fix that fast.
Always find it funy (in a good way) that I have so much contact with people that work for Microsoft and use MSGReader (that is build by me that does not work for Microsoft).... because Microsoft invented the MSG format
Describe the bug .MSG files are not able to be read/parsed on .NET 6 when the code is running on linux.
One of the .NET 6 breaking changes is that it now no longer supports the system.drawing.common on linux. (see .net 6 breaking change here)
The exception you get is:
Error Message: System.TypeInitializationException : The type initializer for 'Gdip' threw an exception. ---- System.PlatformNotSupportedException : System.Drawing.Common is not supported on non-Windows platforms. See https://aka.ms/systemdrawingnonwindows for more information. Stack Trace: at System.Drawing.SafeNativeMethods.Gdip.GdipGetGenericFontFamilySansSerif(IntPtr& fontfamily)
For .NET 5, you are able to install the linux package libgdiplus to have it work, but this no longer is a workaround.
To Reproduce Steps to reproduce the behavior:
Expected behavior The .msg email will be able to be parsed.
Desktop (please complete the following information):