-
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Attachments with umlauts (äöüß) in filenames get corrupted #1691
Comments
Could you please post the raw headers from the message you receive? |
That's the source code
|
The filename is encoded as
It is also missing the content transfer encoding header, so when you save the attachment it does not have its base64 encoding removed. I think that is the actual problem, not the filename, unless the omission of the header is caused by the filename. Needs more investigation... |
Headers without "ö" in filename:
and with "ö":
|
So so... after some experiments: $mime[] = sprintf('Content-ID: <%s>%s', $cid, static::$LE); I added encoding $mime[] = sprintf('Content-ID: <%s>%s', $this->encodeHeader($this->secureHeader($cid)), static::$LE); new headers Content-Type: application/pdf; name="=?utf-8?Q?Sch=C3=B6ne_PDF.pdf?=" Content-Transfer-Encoding: base64 Content-ID: <=?utf-8?Q?Sch=C3=B6ne_PDF.pdf?=> Content-Disposition: attachment; filename="=?utf-8?Q?Sch=C3=B6ne_PDF.pdf?=" Content-Transfer-Encoding is present and attachment is readable |
A few more experiments. Content-Type: image/png; name="=?UTF-8?Q?b=C3=A4ck.png?=" Content-Transfer-Encoding: base64 Content-ID: <2d24120d900f4ac38a3647d02af3de57@Open-Xchange> Content-Disposition: inline; filename="=?UTF-8?Q?b=C3=A4ck.png?=" ... Content-Type: image/png; name="=?utf-8?Q?b=C3=A4ck.png?=" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="=?utf-8?Q?b=C3=A4ck.png?=" X-Part-Id: 2b5928e5976641009b5cd3e59b6a3a46 The header Content-ID is only used for inline attachments. In PHPMailer 5 I have seen the following if ($disposition == 'inline') { $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE); } When I "comment out" the content ID header in version 6, it works as expected. if (!empty($cid) && ($disposition == 'inline')) { $mime[] = sprintf('Content-ID: <%s>%s', $this->encodeHeader($this->secureHeader($cid)), static::$LE); } headers Content-Type: image/png; name="=?utf-8?Q?b=C3=A4ck.png?=" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="=?utf-8?Q?b=C3=A4ck.png?=" I am not a specialist in Email Headers and I do not know exactly how it is right, but I hope that my experiments will help you. |
Hello, solves the problem. |
Please let me know if these changes fix the issues you were having |
Hello Synchro. $cid = 'schön';
$mime = 'Content-ID: ' . $mailer->encodeHeader('<' . $mailer->secureHeader($cid) . '>') . "\r\n";
//-> Content-ID: =?utf-8?Q?<sch=C3=B6n>?=
//v.6.1.1 has another code
$mime2 = sprintf(
'Content-ID: <%s>%s',
$mailer->encodeHeader($mailer->secureHeader($cid)),
"\r\n"
);
//-> Content-ID: <=?utf-8?Q?sch=C3=B6n?=> My suggestion would be, as I've already written here #1691 (comment): if (!empty($cid) && ($disposition == 'inline')) {
$mime[] = sprintf(
'Content-ID: <%s>%s',
$this->encodeHeader($this->secureHeader($cid)),
static::$LE
);
} I fixed PHPMailer that way, and so far I have no problem. Best regards |
I was looking at this again - the changes you mention were introduced for #1864, however, that solution is wrong too, as described in this comment, because RFC2047 encoding is (officially) not supported in Content-ID headers, so a solution more like @adnsistemas suggested would be safer. |
This raises a slight problem. Given that |
Further down the rabbit hole, I ran into RFC2231, which deals with this exact problem! That said, it's still quite confusing, and introduces yet another encoding scheme. So now I need to nail down whether the 2047 encoding should be applied inside or outside the |
Hi, I know very little on the subject, but from the little research I did to "fix" the issue I was having, I don't see any use for the 'cid' other that internally referencing the MIME parts. |
Well ,that's exactly what cid values are for, and if you are writing the HTML yourself, then you're also writing the cid values, and thus need to be able to add attachments with matching values, so that's why it's allowed. The only place where PHPMailer creates cid values itself is in The reason for using user-supplied values (and defaulting to the filename) is that those values are usually more readable - for example |
well then... experiments) $mail = new PHPMailer(); //v.6.1.1
$mail->setFrom('[email protected]');
$mail->Mailer = 'smtp';
$this->CharSet = PHPMailer::CHARSET_UTF8;
$mail->SMTPAuth = true;
$mail->Host = 'mail.example.com';
$mail->Username = '[email protected]';
$mail->Password = 'pass';
$mail->addAddress('[email protected]');
$mail->isHTML(true);
$mail->Subject = 'Test mail';
$filename = 'schönes bild.gif';
//body see below
$mail->send() Definitions: SEND_METHOD_Body: $mail->Body = '<p>Ich habe ein Bild für dich: <img src="cid:'.$mail->encodeHeader($mail->secureHeader($filename)).'" alt="'.$filename.'"></p>';
$mail->addEmbeddedImage(__DIR__ . DIRECTORY_SEPARATOR . $filename, $filename); SEND_METHOD_msgHTML: $mail->msgHTML('<p>Ich habe ein Bild für dich: <img src="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/'.$filename.'" alt="'.$filename.'"></p>', __DIR__); OK: the image in the client is visible
CONTENT_ID_1 + SEND_METHOD_msgHTML
CONTENT_ID_2 + SEND_METHOD_Body
CONTENT_ID_2 + SEND_METHOD_msgHTML
#######################################
So, my choice is still, because then I have at least one possibility that works everywhere: if (!empty($cid) && ($disposition == 'inline')) {
$mime[] = sprintf(
'Content-ID: <%s>%s',
$this->encodeHeader($this->secureHeader($cid)),
static::$LE
);
} Sorry, I could not shorter) Best regards |
When I switched off the maxLength in encodeHeader, CONTENT_ID_1 + SEND_METHOD_msgHTML also worked everywhere ...
if ('mail' == $this->Mailer) {
$maxlen = static::MAIL_MAX_LINE_LENGTH - $overhead;
} else {
$maxlen = static::STD_LINE_LENGTH - $overhead;
}
$maxlen = 10000000;
...
Of course this is not a solution. |
Ohh, ok I get the idea now. Didn't know about building the HTML yourself for the body. |
Maybe in msgHTML() |
Thanks for your work there @eddi13. Are you both using latest code? I pushed a change several days ago in 809394f that uses 32-char truncated sha256 hashes (same length as md5, but without the associated security problems) for cids generated in I agree that returning cids is a good solution, but it will have to wait for a major release for the BC break. In the mean time I think we should allow it to break and document that only ascii-compatible cids are supported. When I look at all these encoding issues and see that other mail libraries have largely not handled them either, it makes me want to restart from scratch and build a proper library! PHPMailer has so much legacy baggage that it's very hard to change stuff. |
So. We have 2 issues with CID - length and encoding. Solution for encoding: if (!empty($cid) && ($disposition == 'inline')) {
$mime[] = sprintf(
'Content-ID: <%s>%s',
$this->encodeHeader($this->secureHeader($cid)),
static::$LE
);
} This solves ALL problems of inline attachments, even if the CIDs have not ascii symbols (e.g. "schönes bild.gif"). with 'Content-ID: ' . $this->encodeHeader('<' . $this->secureHeader($cid) . '>') . static::$LE; the whole thing will not work for non ascii!!! |
See recent pushes for these changes. Also note major revision of DKIM merged to master. |
Hello.
If the attachment name contains an umlaut, the file at the receiver is not readable due to incorrect encoding.
Schöne PDF.pdf
Best regards
Eduard Töws
The text was updated successfully, but these errors were encountered: