12.19.2014

How I got around the Notes C API problem with MailAddMessageBodyComposite creating error 315 on larger HTML files

Tags: Notes C API
0
I have always wanted to be able to import HTML into Notes with the C API in a proper way. Well ... as "proper" as proper can be. We all know that the quality and fidelity of the HTML import in Notes can be so-so, but it is always nicer to be able to do some import rather than none.

To make a long story short, searching around on the net points you to some few pages outlining techniques using the undocumented function ImportHTMLTextFile in the import DLL niHTML.dll. This is probably the very same function the Notes client uses when you import a HTML file into a rich text field. The ImportHTMLTextFile function swallow parameters specifying the URL you want to import, and generates a CD-record file. This is in essence a file with the CD-records as you would believe they would occure in the rich text field. To understand more about CD-records, take a look here. In order to transport the CD-records from the file generated by the ImportHTMLTextFile -function, we use another function named MailAddMessageBodyComposite. Looking in the reference guide it clearly states "This function creates multiple items of the same name and therefore is not limited to 64KB of input". Below you see a snippet of C/C++ code using these functions (note, all error handling is removed for clarity)

/* Prime the Import function with a temporary CD file name and create the CD-record file*/
EDITIMPORTDATA stImpExp;
ZeroMemory(&stImpExp,sizeof(EDITIMPORTDATA));
CopyCStringToChar(strTempCDFile,stImpExp.OutputFileName,OLDMAXPATH);

/* Import the HTML with the undocumented import function in the Import Library NIHTML.DLL from Notes */
error = m_dllImportHTML.ImportHtmlTextFile(&stImpExp,3,0,"",szHTMLFileName);

/* Coming here, we are ready to use the MailAddMessageBodyComposite */
error = NSFItemDelete(m_hDocNote,szRichTextFieldName, strRichTextFieldName.GetLength());
error = MailAddMessageBodyComposite(m_hDocNote,szRichTextFieldName,stImpExp.OutputFileName);

Running the code above on URLs with code below 64 KB went fine, but when the page-size grew beyond 64 KB I got error 315 .... "Memory Allocation Exceeded 65,000 bytes" from MailAddMessageBodyComposite. The ImportHtmlTextFile-function didn't have any problems swallowing huge pages. The 315-error led me to post the question Has anybody got the C API function MailAddMessageBodyComposite working with larger HTML? on the Notes 9 forum.

Since I didn't get any answers, and couldn't get MailAddMessageBodyComposite to work, I finally got my head around the MIME-functions in the C API and the following technique worked nicely - also with huge pages!

In order to get the pseudo-code to work, you must have your HTML file local first. Let's say it is stored as c:\temp\MyHTML.htm. Please note that the code below is not complete nor has error handling in place. Also note that the variable m_docNote is the NOTEHANDLE of the open note. The note will of course be saved after a successful import.

STATUSerror = NOERROR;
MIMEHANDLE        hMIMEStream;

/* Open a MIME stream. This will receive the strings from the file */        
error = MIMEStreamOpen(m_hDocNote, // note handle
        NULL,                               // item name
        0,                               // item name length
        MIME_STREAM_OPEN_WRITE,         // open flags
        &hMIMEStream );

/* Tell the stream that we will receive HTML soon */
error = MIMEStreamPutLine("Content-Type: text/html", hMIMEStream);

/* Loop through the lines in the file. You can use any kind of array or iterator here as long as you can get the file line-by-line */
for (lCur = 0; lCur < lMax; lCur++)
{
        error = MIMEStreamPutLine((char *)arrayFile[lCur], hMIMEStream);
}

/* Delete any potential field with the specified name and convert the MIME Stream to an itemized field */
error = NSFItemDelete(m_hDocNote,"Body", 4);
error = MIMEStreamItemize( m_hDocNote,
                "Body",
                4,
                MIME_STREAM_ITEMIZE_BODY,
                hMIMEStream);

/* Close MIME Stream */
MIMEStreamClose(hMIMEStream);

The pepper in the code above is simply to put the "Content-type"-string into the stream so the MIMEStreamItemize later understand the text as HTML. Also note that the flag MIME_STREAM_ITEMIZE_BODY limits the itemizer to render only the body field of the incoming mime.

Knowing that this technique worked with "fake MIME" as described above, I also tried to use the technique with real MIME files such as EML (drag a mail document from your inbox to your desktop and voila - you have an EML file of that mail!) or other MIME files. The code even imported embedded images without any problem.

Hopefully these tips are helpful if you struggle with MailAddMessageBodyComposite!

Tags

Calendar