Save as HTML

Hello,
I could not figure out how to save the message as HTML, if my memory serves me, I think already asked and no working solution provided.

Of course using HtmlSaveOptions.ResourceRenderingMode = EmbedIntoHtml is the best and easiest way to save a compact, all-in-one html file, this works.

But also need to be able to save like browsers, in IE/Windows this is the behavior:
The file is saved in the destination directory (ie, blah.html)
Beside the file a folder is created named “blah_files” and all the resources are saved there, in the html file referring to that location!

Windows keeps these together, if you delete the html file, the folder will also be deleted and vise versa!

Anyhow, please advise how to save the loaded eml/msg as html like this?
Thanks for your help :slight_smile:

A second query would be the strange MhtSaveOptions.Timeout property
We’ve seen Timeouts mostly in communications, even for large data transfer/saving, as long as it’s in progress the timeout counter does not start counting, and due to sensitive nature of saving files, I’ve no idea what’s its description, under which conditions it starts counting and what happens when a timeout occurs?!
Considering giant fast speed processors and memories on the systems nowadays, and ultra fast SSDs, how is it possible that saving an html/mht file will take more than 3 seconds, considering any processing for such files, the only thing I can imagine, is if we’re going to decode/verify /sign/encrypt the files and it needs to contact the certificate authority’s servers!
Anyway, this is only for mht, not html, eml/msg etc, what’s so special about saving as mht, which is almost the same as eml?
Best :slight_smile:

@australian.dev.nerds,

I could not figure out how to save the message as HTML, if my memory serves me, I think already asked and no working solution provided.

Dim msg As MailMessage = MailMessage.Load(Path.Combine(path, "my.msg"), New MsgLoadOptions())
Dim htmlSaveOptions As HtmlSaveOptions = New HtmlSaveOptions With {
        .ResourceRenderingMode = ResourceRenderingMode.SaveToFile
}
htmlSaveOptions.SaveResourceHandler += SaveResourceHandler
msg.Save(Path.Combine(path, "my.html"), htmlSaveOptions)
Private Sub SaveResourceHandler(ByVal attachment As AttachmentBase, <Out> ByRef resourceFileName As String)
    Dim resourceDir As String = Path.Combine(path, "my_files")

    If Not Directory.Exists(resourceDir) Then
        Directory.CreateDirectory(resourceDir)
    End If

    resourceFileName = Path.Combine(resourceDir, attachment.ContentType.Name)
    attachment.Save(resourceFileName)
End Sub
1 Like

Hello and thanks for the code snippet,
In VB (if I’m right):

htmlSaveOptions.SaveResourceHandler += SaveResourceHandler
:
AddHandler htmlSaveOptions.SaveResourceHandler, SaveResourceHandler

While it will show errors:
Argument not specified for parameter ‘attachment’ of Private Sub SaveResourceHandler
Argument not specified for parameter ‘resourceFileName’ of Private Sub SaveResourceHandler
Pretty confused :frowning:

@australian.dev.nerds,

Sorry, at the end of the working day I mixed up VB and C#.
I write C# example first since it is primary for me.
Here is the correct code in VB.

Dim msg As MailMessage = MailMessage.Load(Path.Combine(myPath, "my.msg"), New MsgLoadOptions())
        Dim htmlSaveOptions As HtmlSaveOptions = New HtmlSaveOptions With {
        .ResourceRenderingMode = ResourceRenderingMode.SaveToFile
}
        htmlSaveOptions.SaveResourceHandler = AddressOf SaveResource

        msg.Save(Path.Combine(myPath, "my.html"), htmlSaveOptions)
Private Sub SaveResource(ByVal attachment As AttachmentBase, ByRef resourceFileName As String)
        Dim resourceDir As String = Path.Combine(myPath, "my_files")

        If Not Directory.Exists(resourceDir) Then
            Directory.CreateDirectory(resourceDir)
        End If

        resourceFileName = Path.Combine(resourceDir, attachment.ContentType.Name)
        attachment.Save(resourceFileName)
    End Sub

Thanks.

1 Like

Hello and thank you very much for clarifying, now works with 2 issues:

  1. Checking the inner html, I see that references to the inline images / resources are like this:
    src=“D:\x_files\image001.png”

While should be:
src=“x_files\image001.png” :: What if we move the html file and its folder to another folder?! Will stop showing the images/resources. It’s also the safest way, because blah.html is saved beside blah_files folder and we can’t separate the html file and its folder, Windows won’t let it.
or:
src=“file:///D:\xok_files\image001.png” :: If we don’t save like this, some browsers like Firefox will not show images at all (although still not ok because if html file/folder is moved, will not show up)

  1. AttachmentBase does not have a .IsInline property, we’re just saving the message body as html and saving the inline resources in its folder so user can view them in browser, we’re not going to save all file attachments inside that folder, which are no use to the html body save nature.
    Wanted to roll out the save by determining the .IsInline property, which does not exist.
    Thanks again :slight_smile:

Hello @australian.dev.nerds,

Here is the updated code of SaveResource handler according to your queries.
I think you will understand it without comments.

Private Sub SaveResource(ByVal attachment As AttachmentBase, ByRef resourceFileName As String)
    resourceFileName = String.Empty

    If Not (TypeOf attachment Is LinkedResource) Then
        Return
    End If

    Dim resourceDir = Path.Combine(myPath, "my_files")

    If Not Directory.Exists(resourceDir) Then
        Directory.CreateDirectory(resourceDir)
    End If

    resourceFileName = Path.Combine("my_files", attachment.ContentType.Name)

    attachment.Save(Path.Combine(resourceDir, attachment.ContentType.Name))
End Sub

Thank you.

1 Like