Codeigniter: PDF attachment contents missing in Outlook Emails on CI 3.1.0

Created on 29 Jul 2016  ·  14Comments  ·  Source: bcit-ci/CodeIgniter

Hi there,

Our problem had developed once we had upgraded to version 3.1.0. We had been including .pdf documents within our emails for a year now. For various purposes, on CodeIgnitier versions 3.0.4 & 3.0.0 prior to that. Our initial code hadn't changed and we started to receive 'blank' .PDFs, they were successfully attached however, it seems the contents were empty; corrupted and/or unsuccessfully included to the Email when being attached in Outlook.

I managed to produce a test case for this below, of which if you do spot a possible mistake, please let me know:

<?php
/**
 * 
 */
class SandboxCI extends CI_Controller {

    /**
     * 
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * 
     */
    private function get_pdf_path()
    {
        $file_path = FCPATH . 'assets/sandbox/hello_world.pdf';

        if ( !file_exists( $file_path ))
        {
            log_message( "debug", "Attempted to get file at: $file_path" );
            return false;
        }
        else
        {
            return $file_path;
        }
    }

    /**
     * 
     */
    public function send_email()
    {
        //Clear just in case.
        $this->email->clear(TRUE);

        //Init
        $this->email->initialize(array(
            'mailtype'  => 'html',
            'protocol'  => 'sendmail',
            'mailpath'  => '/usr/sbin/sendmail',
            'charset'   => 'utf-8',
            'wordwrap'  => TRUE,
            'validate'  => TRUE
        ));

        //Get a dummy 'Hello World!' pdf that we've saved locally. 
        $pdf = $this->get_pdf_path();

        if ( !$pdf )
        {
            log_message( "error", "Test PDF not found" );
            return false;
        }

        $this->email
             ->to( "[email protected]" )
             ->from( "[email protected]" )
             ->subject( "Test Attachtment on CI ". CI_VERSION );

        //Location: home/site/assets/sandbox/hello_world.pdf
        if ( !$this->email->attach( $pdf ))
        {
            echo '<pre>Unable to attach the PDF</pre>';
            return false;
        }

        $message = '<html><body><h1>Hello, World!</h1></body></html>';

        $this->email->message( $message );
        $sent = $this->email->send( FALSE );

        if (  $sent )
        {
            echo 'Email sent';
        }
        else
        {
            echo 'Failed to send Email';
        }

        echo '<hr /><pre>'. $this->email->print_debugger() .'</pre>';
        return $sent;
    }
}

Once arrived at your Inbox in Outlook. it will appear as, at 240 Bytes, just the space reserved for a .pdf

image

image

The $this->_attachments at _append_attachments() appears to have the correct variables filled:

 Array
(
    [0] => Array
        (
            [name] => Array
                (
                    [0] => /public_html/assets/sandbox/hello_world.pdf
                    [1] => 
                )
            [disposition] => attachment
            [type] => application/pdf
            //Cut down for easier reading..
            [content] => JVBERi0xLjUNCiW1tbW1DQoxIDAgb2JqDQo8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFIvTGFu
Zyhlbi1HQikgL1N0cnVjdFRyZWVSb290IDEyIDAgUi9NYXJrSW5mbzw8L01hcmtlZCB0cnVlPj4+.....
            [multipart] => mixed
        )
)

Which seems to be OK - However it seems the only difference would be the Email headers, pre/post 3.1.0.

3.1.0 >=

Content-Type: multipart/mixed; boundary="B_ATC_579f0d9ccd677"

This is a multi-part message in MIME format.
Your email application may not support this format.

--B_ATC_579f0d9ccd677
Content-Type: multipart/alternative; boundary="B_ALT_579f0d9ccd5cc"

--B_ALT_579f0d9ccd5cc
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Hello, World!


--B_ALT_579f0d9ccd5cc
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

=3Chtml=3E=3Cbody=3E=3Ch1=3EHello, World=21=3C/h1=3E=3C/body=3E=3C/html=3E

--B_ALT_579f0d9ccd5cc--



--B_ATC_579f0d9ccd677
Content-Type: application/pdf; name="hello_world.pdf"
Content-Disposition: attachment;
Content-Transfer-Encoding: base64
JVBERi0xLjUNCiW1tbW1DQoxIDAgb2JqDQo8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFIvTGFu
Zyhlbi1HQikgL1N0cnVjdFRyZWVSb290IDEyIDAgUi9NYXJrSW5mbzw8L01hcmtlZCB0cnVlPj4+

<= 3.0.6

Content-Type: multipart/mixed; boundary="B_ATC_579f0a9379cc6"

This is a multi-part message in MIME format.
Your email application may not support this format.

--B_ATC_579f0a9379cc6
Content-Type: multipart/alternative; boundary="B_ALT_579f0a9379c49"

--B_ALT_579f0a9379c49
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

Hello, World!


--B_ALT_579f0a9379c49
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

=3Chtml=3E=3Cbody=3E=3Ch1=3EHello, World=21=3C/h1=3E=3C/body=3E=3C/html=3E

--B_ALT_579f0a9379c49--

--B_ATC_579f0a9379cc6
Content-type: application/pdf; name="hello_world.pdf"
Content-Disposition: attachment;
Content-Transfer-Encoding: base64

JVBERi0xLjUNCiW1tbW1DQoxIDAgb2JqDQo8PC9...

Reverting the Email.php helper to version 3.0.4 worked fine, however I'm not entirely sure on how the RFC Headers should be created for such instances.

If you need anymore test data; please let me know!

Cheers,
Robert.

Bug Regression

Most helpful comment

Had the same problem couple of weeks back with email attachments not working... switched to phpmailer...

Thank you, that is very helpful.

All 14 comments

Ok, there's two things I see at first glance ...

  1. You're comparing 3.0.4 to 3.1.0, which means you're skipping 2 versions in between - 3.0.5 and 3.0.6. Please verify the exact "point of failure".
  2. There _are_ changes related to attachments in 3.1.0 (see #4583), but they don't relate to the Subject encoding. In fact - there are _zero_ changes affecting this between 3.0.4 and 3.1.0, which leads me to believe you're also doing something else different (maybe a different environment? idk)

Either way, we do need more details.

Had the same problem couple of weeks back with email attachments not working... switched to phpmailer...

Had the same problem couple of weeks back with email attachments not working... switched to phpmailer...

Thank you, that is very helpful.

will do some testing later today... :-)

Good morning!

Having downloaded & tested 3.0.5 - there's no problem. Attachment appears should, at 257 _Kilobytes_ with the contents intact & un-corrupted. Made a couple of changes to the code at thread start to make sure the filesize is of a suspected size & $mail->attach() is separated into it's on if() statement, just to make sure it's not failing.

Secondly, I realised it wasn't very helpful publishing the headers; as it's the boundaries of the multi-part data that's the important thing here, which there's been subtle changes between 3.0.5 & 3.1.0. (Should there be a newline after Content-Transfer-Encoding: base64 on 3.1.0?). The charset is cased differently, however I do specify that at the email config.

As for the Email Client, I'm using Outlook 2010 & Outlook.com Webmail which both had the same issue.

I have tested this with my gmail and it is correctly showing the PDF intriguingly. So could just be an Edge case.

@MackieeE Thanks for the further input, I'll try to see if I there's any clue in there.

However, please don't edit your original (and already long enough message) - it makes my replies senseless and the conversation hard to follow.

@narfbg Quite right; I'll put any further input as a new comment for future references. I can understand a year from now it may look like a complete jumbled conversation :)

This is all being tested with PHP 7.0.8 mind you; If there's anything else you'd like me to change or test. Please let me know!

Indeed, a second newline characters is missing and I'm quite sure that's not intentional.

Is that the problem for sure?

That seems to be it. Since adding an intentional extra $this->newline, it's worked perfectly.

image

I'm running the server on _Ubuntu 14.04.01_ and this has also been tested on _Redhat 4.4_ as well. Both producing the same result a missing newline at: _append_attachments

However it _should_ add a newline regardless before & after (empty($this->_attachments[$i]['cid']) but this isn't showing at the debug. I'm guessing the OS in question isn't treating the \n correctly.

It doesn't matter what you test it on server-side, that code is platform-independent.

Anyway, the referenced commit should fix it.

对比正常的邮件原文和ci发出的邮件原文,发现CI发出的附件“Content-Transfer-Encoding: base64”和附件的正文内容编码间缺少一个换行符,
查看CI的内核/libraries/Email.php文件,
1470行,.'Content-Transfer-Encoding: base64'.$this->newline

在后面再添加一个".$this->newline"问题解决。

另,在1471行,.(empty($this->_attachments[$i]['cid']) ? '' : 'Content-ID: <'.$this->_attachments[$i]['cid'].'>'.$this->newline.$this->newline)
可以看出,如果指定了附件的id,貌似会换行两次,如果没有指定,附件将无法下载。

需要修改内核文件才解决问题,这个bug比较低级,希望官方尽快处理,我的版本是3.1.0

Adding extra "$this->newline" works for me.
Was:
. 'Content-Transfer-Encoding: base64' . $this->newline
Is:
. 'Content-Transfer-Encoding: base64' . $this->newline. $this->newline

@skycyclone 这种修复它,非常感谢你

@skycyclone @vhuerta We speak English. Not a clue what you are trying to say, and your comments are not helpful!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Tjoosten picture Tjoosten  ·  6Comments

huehnerhose picture huehnerhose  ·  6Comments

it-can picture it-can  ·  5Comments

alexmason528 picture alexmason528  ·  6Comments

Rverm picture Rverm  ·  6Comments