Search This Blog

Thursday, October 24, 2019

Non-ASCII filenames and NotesMimeEntity/NotesMimeHeader

Hi

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;
filename=bbbdoc.docx
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;
filename="éééééédoc.docx"
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) 

to

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: https://blog.nodemailer.com/2017/01/27/the-mess-that-is-attachment-filenames/ from which I got the main idea.

No comments:

Post a Comment