Email – přiložený soubor a podivné %09 před názvem souboru

Alsatian
Člen | 164
+
0
-

Ahoj.
Pokud přiložím soubor k emailu a má delší název, třeba
lorem-ipsum-dlouhy-text-nazvu-pdf-dokumentu.jpg

tak jej v příloze odeslaného emailu vidím normálně, ale pokud dám uložit soubor na disk, název obsahuje %09 na jeho začátku. Tedy zde konkrétně:
%09lorem-ipsum-dlouhy-text-nazvu-pdf-dokumentu.jpg

Pokud zkrátím název souboru na „lorem-ipsum-dlouhy“, při ukládání je v pořádku.

Setkal se s tím někdo? Odesílám klasicky přes nette Nette\Mail\Message a soubor přikládám taky klasicky, viz:

$mail = new Nette\Mail\Message;
$mail->setFrom...
$mail->addBcc...
$mail->addAttachment(__DIR__ . '/../../../temp/lorem-ipsum-dlouhy-text-nazvu-pdf-dokumentu.jpg');

$mailer = new SendmailMailer;
$mailer->send($mail);
Alsatian
Člen | 164
+
0
-

Jak řešit odesílání PDF emailem (používám joseki/pdf-response), kdy při každém vygenerování PDF se toto uloží do definovaného adresáře a následně odešle jako příloha emailu. PDF soubor má vždy jiný název – obsahuje identifikační údaje jako číslo faktury a název a hromadí se v této složce.

iguana007
Člen | 970
+
0
-

Nemas v kodu, kde skladas nazev toho souboru tabulator? Protoze %09 je Tab.

Alsatian
Člen | 164
+
0
-

Vyřešeno přiložením souboru a definováním vlastního názvu. Ten může být i dlouhý. Prostě nenechávat to na názvu souboru.
Stačí tedy přiložit soubor takto (ostatně viz Nette dokumentace):

$mail->addAttachment('Pekelně dlouhý název souboru a rovnou s diakritikou.zip', file_get_contents('path/to/example.zip'));
xsuchy09
Člen | 6
+
0
-

Narazil jsem na stejný problém. Ovšem v mém případě přikládám přílohu (PDF) s vlastním názvem a i tak se po otevření objeví „%09“ na začátku a při uložení z emailu na disk je dané nahrazeno pomlčkou (Thunderbird + Ubuntu). Příloha v emailu má název OK, dané se děje až v okamžiku otevření/stažení souboru z emailu. V daném stringu (v definovaném názvu souboru) tab ani jiné není … nette/mail v3.1.0

edit: Ve vygenerovaném emailu je příloha skutečně přiložena takto:

Content-Type: application/pdf
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="
	nazev-souboru.pdf"

edit2: Problém bude v \Nette\Mail\MimePart:getEncodedHeader (+ následně využívané \Nette\Mail\MimePart:encodeHeader a \Nette\Mail\MimePart:append).

Editoval xsuchy09 (11. 3. 2020 9:15)

Gappa
Nette Blogger | 199
+
0
-

xsuchy09 napsal(a):

Narazil jsem na stejný problém. Ovšem v mém případě přikládám přílohu (PDF) s vlastním názvem a i tak se po otevření objeví „%09“ na začátku a při uložení z emailu na disk je dané nahrazeno pomlčkou (Firefox + Ubuntu). Příloha v emailu má název OK, dané se děje až v okamžiku otevření/stažení souboru z emailu. V daném stringu (v definovaném názvu souboru) tab ani jiné není … nette/mail v3.1.0

edit: Ve vygenerovaném emailu je příloha skutečně přiložena takto:

Content-Type: application/pdf
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="
	nazev-souboru.pdf"

edit2: Problém bude v \Nette\Mail\MimePart:getEncodedHeader (+ následně využívané \Nette\Mail\MimePart:encodeHeader a \Nette\Mail\MimePart:append).

%09 je CHARACTER TABULATION, horizontal tabulation (HT), tab. Nepodařilo se ten tab tam nějak omylem zkopírovat?

xsuchy09
Člen | 6
+
0
-

Ne, podle mě to vzniká tady \Nette\Mail\MimePart:getEncodedHeader (134 – 138):

		} elseif (preg_match('#^(\S+; (?:file)?name=)"(.*)"\z#', $this->headers[$name], $m)) { // Content-Disposition
			$offset += strlen($m[1]);
			return $m[1] . '"' . self::encodeHeader($m[2], $offset) . '"';

		} else {

edit:
viz test:

		} elseif (preg_match('#^(\S+; (?:file)?name=)"(.*)"\z#', $this->headers[$name], $m)) { // Content-Disposition
			$offset += strlen($m[1]);
			Debugger::log($this->headers[$name], ILogger::DEBUG);
			$ret = $m[1] . '"' . self::encodeHeader($m[2], $offset) . '"';
			Debugger::log($ret, ILogger::DEBUG);
			return $ret;
		} else {

log:

[2020-03-11 08-08-17] attachment; filename="invoice-vqbDn5QLdPzye3z1VJX8NyMWg.pdf"
[2020-03-11 08-08-17] attachment; filename=" invoice-vqbDn5QLdPzye3z1VJX8NyMWg.pdf"

Takže to přidává encodeHeader, jak jsem zmiňoval výše … debugnu to až do konce …

Editoval xsuchy09 (11. 3. 2020 8:12)

xsuchy09
Člen | 6
+
+1
-

Ano, vzniká to zde (134 – 136)

		} elseif (preg_match('#^(\S+; (?:file)?name=)"(.*)"\z#', $this->headers[$name], $m)) { // Content-Disposition
			$offset += strlen($m[1]);
			return $m[1] . '"' . self::encodeHeader($m[2], $offset) . '"';

poté zavolá 285:

return self::append($s, $offset);

a to následně MimePart:append – kde to přidá řádek 310 ($s = self::EOL . "\t" . $s;):

	private static function append(string $s, int &$offset = 0): string
	{
		if ($offset + strlen($s) > self::LINE_LENGTH) {
			$offset = 1;
			$s = self::EOL . "\t" . $s;
		}
		$offset += strlen($s);
		return $s;
	}

Řešení je změnit 134 – 136:

		} elseif (preg_match('#^(\S+; (?:file)?name=)(".*")\z#', $this->headers[$name], $m)) { // Content-Disposition
			$offset += strlen($m[1]);
			return $m[1] . self::encodeHeader($m[2], $offset);

A pak je výsledek OK:

Content-Disposition: attachment; filename=
	"invoice-7lQYGxp6er2Dpb28ZdDvPOoML.pdf"

Ale nejsem si jist, zda je obecně řešení přidání těch uvozovek do MimePart:encodeHeader v pořádku. Pro tento případ asi ano, ale tam kde se použije řádek 283 asi ne.

Dle RFC není toto rozdělení v hlavičce asi nutné:

3.4.8. FOLDING LONG HEADER FIELDS

Each header field may be represented on exactly one line con-
sisting of the name of the field and its body, and terminated
by a CRLF; this is what the parser sees. For readability, the
field-body portion of long header fields may be „folded“ onto
multiple lines of the actual field. „Long“ is commonly inter-
preted to mean greater than 65 or 72 characters. The former
length serves as a limit, when the message is to be viewed on
most simple terminals which use simple display software; how-
ever, the limit is not imposed by this standard.

Note: Some display software often can selectively fold lines,
to suit the display terminal. In such cases, sender-
provided folding can interfere with the display
software.

edit: Koukám, že už existuje i issue https://github.com/…il/issues/24 … každý OS/klient se s tím evidentně popere jinak. Každopádně to zapříčiňuje chybné jméno přílohy a považuji to tedy za bug.

@DavidGrudl

Editoval xsuchy09 (11. 3. 2020 8:55)

David Grudl
Nette Core | 8133
+
+1
-

Díky, opraveno.

To rozdělování hlaviček do 80 znaků je bolest, ale nejsem si jist, jestli je to stále v dnešní době potřeba, jestli by nevznikly problému kvůli nějakým serverům atd…

Zkusím to zvednout na 500 a uvidíme.