php-imap icon indicating copy to clipboard operation
php-imap copied to clipboard

Attachment names not being parsed

Open gRoberts84 opened this issue 1 year ago • 1 comments

Describe the bug When attempting to store attachments from a retrieved email, the names are returned as 8 characters instead of the original filename.

When checking the headers of the attachment object, you can see the filename is being treated as a separate header and is being split into two sections as the name/value.

Used config Using default.

Code to Reproduce The troubling code section which produces the reported bug.

foreach ($message->getAttachments() as $attachment) {
    var_dump($attachment->getName());
}

Expected behavior Expect to see the actual filename, but get an 8 digit code, e.g. 616ca634.

Screenshots If applicable, add screenshots to help explain your problem.

Desktop / Server (please complete the following information):

  • OS: [e.g. Debian 10] OSX Ventura
  • PHP: [e.g. 5.5.9] 8.2.15
  • Version [e.g. v2.3.1] 5.3.0
  • Provider [e.g. Gmail, Outlook, Dovecot] Gmail

Additional context Attachment header:

Content-Type: message/rfc822;
Content-Transfer-Encoding: base64
X-Attachment-Id: f_lrosxhxg0
name="xxxxxxxxxxxxxxx Your Reference (ref: xxxxxxxxxx).eml"
filename="xxxxxxxxxxxxxxx Your Reference (ref: xxxxxxxxxx).eml"
Content-ID: <f_lrosxhxg0>
Content-Disposition: attachment;

Parsed header:

["filename="xxxxxxxxxxxxxxx your reference (ref"]=>
  object(Webklex\PHPIMAP\Attribute)#2074 (2) {
    ["name":protected]=>
    string(45) "filename="xxxxxxxxxxxxxxx your reference (ref"
    ["values":protected]=>
    array(1) {
      [0]=>
      string(16) "xxxxxxxxxx).eml""
  }
}

gRoberts84 avatar Feb 13 '24 10:02 gRoberts84

As a temporary workaround, I am having to parse the filename myself, however the attachment attachment keys are converted to lowercase, which isn't ideal:

// Loop through attachments and store them.
$backup_filename = false;
foreach ($message->getAttachments() as $attachment) {
    $name = $attachment->name;
    if ($name === $attachment->hash) {
        foreach ($attachment->getAttributes() as $key => $value) {
            if (stripos($key, 'filename="') !== false) {
                $name = preg_replace('/filename="([^"]+)"/', '$1', sprintf('%s: %s', $key, $value));
            }
        }
    }
    if ($name === $attachment->hash) {
        $name = $backup_filename;
    } else {
        $backup_filename = $name;
    }
    // Do something with the attachment...
}

In the EML with the issue, only one of the attachments has the filename/name headers, the rest are similar to:

Content-Type: message/rfc822;
Content-Transfer-Encoding: base64
X-Attachment-Id: f_lrosxhy12
Content-ID: <f_lrosxhy12>
Content-Disposition: attachment;

Gmail shows the attachments all with the same filename, hence the backup filename.

gRoberts84 avatar Feb 15 '24 09:02 gRoberts84