Search This Blog

Thursday, October 24, 2019

Non-ASCII filenames and NotesMimeEntity/NotesMimeHeader


If you need to compose outgoing email with NotesMIMEEntity and NotesMIMEHeader and send attachment with it then you can do it by writing something like this:

Dim body As NotesMIMEEntity
Dim header As NotesMIMEHeader
Dim stream As NotesStream
//Here we define root entity for the tree
Set body = NotesDoc.CreateMIMEEntity("Body")
Set header = body.CreateHeader("MIME-Version") 
Call header.SetHeaderValAndParams(|1.0|)
Set header = body.CreateHeader("content-type") 
Call header.SetHeaderValAndParams(|multipart/mixed|)

//Then we can create any number of needed child entities with plain text, html, inline images and so on
Set child1 = body.CreateChildEntity()
Call child1.SetContentFromText (someStreamWithSomeContent, "text/plain;charset=utf-8", ENC_NONE) 
Set child2 = body.CreateChildEntity()
Call child2.SetContentFromText (someStreamWithSomeContent, "text/html;charset=utf-8", ENC_NONE) 
Set child3 = body.CreateChildEntity()
Call child3.SetContentFromText (someStreamWithSomeContent, "whatever;charset=utf-8", ENC_NONE) 

//Finally we create an entity for file
Call stream.Truncate()
Call stream.Open(filepath, "binary") 

Set child = body.CreateChildEntity()
Set header = child.CreateHeader("Content-Disposition") 
Call header.SetHeaderValAndParams({attachment; filename="} & filename & {"})
Call child.SetContentFromBytes(stream, "application/octet-stream", ENC_IDENTITY_BINARY) 
child.EncodeContent ENC_BASE64 

Call stream.close()

The block above works good for files containing only ASCII characters in name.
However if you try to send file with name like éééééédoc.docx - you would not receive original filename but this - see below

Content-Type: application/octet-stream
Content-Disposition: attachment;
Content-Transfer-Encoding: base64

I have fixed this problem by changing line below:

Call header.SetHeaderValAndParams({attachment; filename="} & filename & {"})

To this:

Call header.SetHeaderValAndParams({attachment; filename*=utf-8''} & Join(Evaluate({@URLEncode("UTF-8";"} & filename & {")})))

Then you will get correct result:

Content-Type: application/octet-stream
Content-Disposition: attachment;
Content-Transfer-Encoding: base64

During testing I discovered that some of Mail-clients still displayed filename in a wrong way, f.x. filename could be correct in Notes-client but wrong in iNotes (Chrome).
I have fixed that last problem by replacing line

Call child.SetContentFromBytes(stream, "application/octet-stream", ENC_IDENTITY_BINARY) 


Call child.SetContentFromBytes stream, {application/octet-stream;name="=?utf-8?Q?} & Replace(Join(Evaluate({@URLEncode("UTF-8";"} & filename & {")})), "%", "=") & {?="}, ENC_IDENTITY_BINARY)

All credits to author of this post: from which I got the main idea.

No comments:

Post a Comment