Jonniboy
Jonniboy

Reputation: 136

CodeIgniter's mail library sends a mail with an empty attachment

I'm using CodeIgniter's email library to send a mail to myself for testing. This email should have an attachment, so I use the following code for sending the mail:

$this->load->library('colorparser');
$this->load->library('email');

$config = array();
$config['mailtype'] = 'html';

$this->email->initialize($config);

$this->email->from('...', '...');
$this->email->to('...');

$this->email->subject('A user sent in a map for your Trackmania tournament');
$this->email->message("some HTML code");
$this->email->attach("/www/htdocs/.../dev/tournois/uploads/tm2/57e30c92aaa65393755646.gif", 'attachment');

$this->email->send();

What makes me curious is that after execution I receive a mail with an attachment. The name is correct and Thunderbird tries to show the gif, but the attachment is empty, 0 bytes.

Then I tried to get the output via print_debugger() which worked just fine. I can't see any error in the information shown by the debugger, even the base64 encoded stuff is there.

Do you've any idea why this is a thing?

Upvotes: 4

Views: 1234

Answers (2)

Jonniboy
Jonniboy

Reputation: 136

I reanalyzed the mail headers & bodies and discovered a missing blank line, which is the problem:

Content-Type: image/gif; name="57e30c92aaa65393755646.gif"
Content-Disposition: attachment;
Content-Transfer-Encoding: base64
R0lGODlhLAGoAPcAADwkGEAnHEMpIEQsIEQtJEgxJks1K082KVM4KVQ9KlQ8Lk85MVI9NFQ/N1JA...

But normally it has to be with two line breaks:

Content-Type: image/gif; name="57e30c92aaa65393755646.gif"
Content-Disposition: attachment;
Content-Transfer-Encoding: base64

R0lGODlhLAGoAPcAADwkGEAnHEMpIEQsIEQtJEgxJks1K082KVM4KVQ9KlQ8Lk85MVI9NFQ/N1JA...

I don't know if this is already fixed in a newer CodeIgniter build, but for everyone having the same problem, you can fix it by editing the Email library by yourself. The library is located in /system/libraries folder. You can overwrite it too (with MY_...), but for short fixing it I just added a second "new line" to the code in the CI library.

This is the original function where CodeIgniter adds attachments to the mail:

protected function _append_attachments(&$body, $boundary, $multipart = null)
{
    for ($i = 0, $c = count($this->_attachments); $i < $c; $i++)
    {
        if (isset($multipart) && $this->_attachments[$i]['multipart'] !== $multipart)
        {
            continue;
        }

        $name = isset($this->_attachments[$i]['name'][1])
            ? $this->_attachments[$i]['name'][1]
            : basename($this->_attachments[$i]['name'][0]);

        $body .= '--'.$boundary.$this->newline
            .'Content-Type: '.$this->_attachments[$i]['type'].'; name="'.$name.'"'.$this->newline
            .'Content-Disposition: '.$this->_attachments[$i]['disposition'].';'.$this->newline
            .'Content-Transfer-Encoding: base64'.$this->newline
            .(empty($this->_attachments[$i]['cid']) ? '' : 'Content-ID: <'.$this->_attachments[$i]['cid'].'>'.$this->newline.$this->newline)
            .$this->_attachments[$i]['content'].$this->newline;
    }

    // $name won't be set if no attachments were appended,
    // and therefore a boundary wouldn't be necessary
    empty($name) OR $body .= '--'.$boundary.'--';
}

Now, to solve the problem, just replace the '' of the Content ID string part with a new line, so if there is no Content ID, there will be the missing new line.

$body .= '--'.$boundary.$this->newline
                .'Content-Type: '.$this->_attachments[$i]['type'].'; name="'.$name.'"'.$this->newline
                .'Content-Disposition: '.$this->_attachments[$i]['disposition'].';'.$this->newline
                .'Content-Transfer-Encoding: base64'.$this->newline
                .(empty($this->_attachments[$i]['cid']) ? $this->newline : 'Content-ID: <'.$this->_attachments[$i]['cid'].'>'.$this->newline.$this->newline)
                .$this->_attachments[$i]['content'].$this->newline;

Hope this helps someone!

Upvotes: 2

PaulD
PaulD

Reputation: 1171

It all looks good so a couple of things to double check that might help.

  1. File permissions are set correctly (try 777 just to be sure then reduce as needed)
  2. Path name is correct. You can also try a URL instead of a path name just to test if it is the pathname or not.
  3. Config includes .gif as an allowable filetype Ignore that one, confusing myself with file uploads.
  4. File actually exists and is not blank.

If you are creating the file on the fly or with a file upload then the error might be occurring there, and not in the email.

Hope that helps.

Upvotes: 1

Related Questions