Ali Alhajji
Ali Alhajji

Reputation: 236

Unicode Characters in Attachment name

I'm trying to write a program that sends PDFs to my Kindle using SMTP.

When I send an attachment to the Kindle using a regular client (i.e. Outlook), I get the correct file name even if it's non-ASCII. However, when I send it using the code, the Unicode characters are not shown correctly. I tried sending the attachment to my personal email and there was nothing wrong in it, only Kindle does not recognize the characters.

This is my attachment headers:


Content-Disposition: attachment; filename="اÙضح٠ÙاÙÙسÙاÙ.pdf"

Content-Transfer-Encoding: base64

Content-Type: application/pdf; name="اÙضح٠ÙاÙÙسÙاÙ.pdf"

And this is my code:

package main

import (
    "log"

    "gopkg.in/gomail.v2"
)

func main() {
    m := gomail.NewMessage()

    m.SetHeader("To", "[email protected]")
    m.SetHeader("From", "[email protected]")
    m.SetBody("text/plain", "")

    path := "C:\\Users\\al111\\Downloads\\Telegram Desktop\\كيف تعمل الماركسية.pdf"
    m.Attach(path)
    d := gomail.NewDialer("smtp.live.com", 587, "[email protected]", "MY-PASSWORD")

    err := d.DialAndSend(m)
    if err != nil {
        log.Fatal(err)
    }
}

Upvotes: 1

Views: 1117

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 598134

RFC 2822 style email headers do not allow unescaped Unicode characters. You need to use an ASCII-compatible encoding, such as RFC20471 or RFC 2231, eg:

Content-Disposition: attachment;
  filename="=?UTF-8?Q?=D9=83=D9=8A=D9=81=20=D8=AA=D8=B9=D9=85=D9=84=20=D8=A7=D9=84=D9=85=D8=A7=D8=B1=D9=83=D8=B3=D9=8A=D8=A9=2E=70=64=66.pdf?="

Content-Type: application/pdf;
  name="=?UTF-8?Q?=D9=83=D9=8A=D9=81=20=D8=AA=D8=B9=D9=85=D9=84=20=D8=A7=D9=84=D9=85=D8=A7=D8=B1=D9=83=D8=B3=D9=8A=D8=A9=2E=70=64=66.pdf?="
Content-Disposition: attachment;
  filename*=UTF-8''%D9%83%D9%8A%D9%81%20%D8%AA%D8%B9%D9%85%D9%84%20%D8%A7%D9%84%D9%85%D8%A7%D8%B1%D9%83%D8%B3%D9%8A%D8%A9%2E%70%64%66.pdf

Content-Type: application/pdf;
  name*=UTF-8''%D9%83%D9%8A%D9%81%20%D8%AA%D8%B9%D9%85%D9%84%20%D8%A7%D9%84%D9%85%D8%A7%D8%B1%D9%83%D8%B3%D9%8A%D8%A9%2E%70%64%66.pdf

1: yes, I'm aware that RFC 2047 technically does not allow encoded-words inside quoted-strings, such as for parameter values. But many servers do allow this.

See:

How to encode the filename parameter value of the Content-Disposition header in MIME message?

The mess that is attachment filenames

It is likely that Outlook is doing exactly this when it sends emails your emails. Which you can verify by looking at the raw data of the emails that it actually sends.

In Go, the m.Attach() function has an optional settings parameter that can be used to pass in additional parameters for an attachment, such as custom filenames and even custom headers, eg:

baseName := mime.QEncoding.Encode("utf-8", filepath.Base(path))
m.Attach(path, gomail.Rename(baseName))
baseName := url.PathEscape(filepath.Base(path))
m.Attach(path, gomail.SetHeader(map[string][]string{
        "Content-Disposition": {"attachment; filename*=UTF-8''" + baseName},
    }))

Upvotes: 2

Related Questions