fuel / email

Fuel PHP Framework - Fuel v1.x Email library
60 stars 38 forks source link

Headers are not MIME encoded #13

Closed felixkoch closed 12 years ago

felixkoch commented 12 years ago

Hey,

in Germany we often send emails with german umlauts in the subject, some email clients can't handle german umlauts if they aren't mime encoded (email headers should only contain ASCII-chars).

My solution (it's not very clean):

class Email_Driver_Mail extends \Email_Driver
{
    /**
     * Send the email using php's mail function.
     *
     * @return  bool    success boolean.
     */
    protected function _send()
    {
        $message = $this->build_message();
        if ( ! @mail(static::format_addresses($this->to), mb_encode_mimeheader($this->subject, 'UTF-8', 'Q'), $message['body'], $message['header'], '-oi -f '.$this->config['from']['email']))
        {
            throw new \EmailSendingFailedException('Failed sending email');
        }
        return true;
    }

}

And in driver.php

protected function get_header($header = null, $formatted = true)
{
    if ($header === null)
    {
        return $this->headers;
    }

    if (array_key_exists($header, $this->headers))
    {
        $prefix = ($formatted) ? $header.': ' : '';
        $suffix = ($formatted) ? $this->config['newline'] : '';

        if($header == "Subject")
        {
            return $prefix.mb_encode_mimeheader($this->headers[$header], 'UTF-8', 'Q').$suffix;
        }

        return $prefix.$this->headers[$header].$suffix;
    }

    return '';
}

Names of email-adresses should be mime-encoded, too: In driver.php I changed:

public function from($email, $name = false)
{
    $this->config['from']['email'] = (string) $email;
    $this->config['from']['name'] = (is_string($name)) ? mb_encode_mimeheader($name, 'UTF-8', 'Q') : false;

    return $this;
}

protected function add_to_list($list, $email, $name = false)
{
    if ( ! is_array($email))
    {
        $email = (is_string($name)) ? array($email => $name) : array($email);
    }

    foreach ($email as $_email => $name)
    {
        if (is_numeric($_email))
        {
            $_email = $name;
            $name = false;
        }

        if($name !== false)
        {
            $name = mb_encode_mimeheader($name, 'UTF-8', 'Q');
        }

        $this->{$list}[$_email] = array(
            'name' => $name,
            'email' => $_email,
        );
    }
}

But this is not the best solution, because if there are dots and other special chars in the email names the name should be quoted. And when they are quoted, extra quotes should be escaped.

This is the reason, why i present my solution as one solution but not as THE solutions. I'm sure, the maintainers will find a better and stable solution, which fits better in the coding style of fuelphp.

Thank you and best regards Felix

felixkoch commented 12 years ago

I think it is better to use the newline-parameter of mb_encode_mimeheader()

 mb_encode_mimeheader($this->headers[$header], 'UTF-8', 'Q', $this->config['newline'])

mb_encode_mimeheader() uses per default \r\n. If you user '\n' instead and the encoded subject line is longer than 76 chars Lotus Notes will break the header and interpretes the next lines of the header as body.

frankdejonge commented 12 years ago

Thanks for the tip! I'll look into this.

WanWizard commented 12 years ago

@FrenkyNet Any chance of picking this up for 1.2?