Location: PHPKode > projects > phlyMail Lite > phlymail/shared/lib/message.encode.php
<?php
/**
 * Routines related to encoding emails
 *
 * @package phlyMail Nahariya 4.0+ Default branch
 * @author Matthias Sommerfeld <hide@address.com>
 * @copyright 2001-2010 phlyLabs Berlin, http://phlylabs.de
 * @version 4.0.3 2010-10-22
 */
// Make sure, compatibility layer is loaded
require_once(dirname(__FILE__).'/compat.5.x.php');
/**
 * Creates a complete mail header based on the input
 *
 * @param array $in standard headers to, cc, bcc, subject
 * @param string $additional  application created header lines (already standards compliant!)
 * @param string $encoding  Encoding for RFC1522
 * @param array $userheaders  Header lines created by the user, cleaned by this function
 * @param bool $uh_before  insert userland headers before or after the standard headers
 * @return string
 */
function create_messageheader($in, $additional = '', $encoding = 'iso-8859-1', $userheaders = array(), $uh_before = false)
{
    $return = '';
    // Instantiate IDNA class
    $IDN = new idna_convert();
    // Clean and encode standard headers
    foreach (array('from', 'to', 'cc', 'bcc', 'subject') as $key) {
        if (!isset($in[$key])) {
            $in[$key] = '';
            continue;
        }
        if (!$in[$key]) continue;
        if (trim($in[$key]) && !$in[$key]) continue;
        switch ($key) {
            case 'from': case 'to': case 'cc': case 'bcc':
                $in[$key] = multi_address($in[$key], 0, 'send', 0);
                break;
        }
        // Suche nach QP-Teilen
        if (preg_match('/[\x80-\xff]/', $in[$key])) {
            $cmode = 'n';
            switch ($key) {
            case 'subject':
                $cmode = 'g';
                break;
            case 'from': case 'to': case 'cc': case 'bcc':
                $cmode = '@';
                break;
            }
            $in[$key] = encode_1522_line_q(decode_utf8(rtrim($in[$key]), $encoding), $cmode, $encoding);
        }
    }
    // Clean and encode user header lines
    $userheader = '';
    foreach ($userheaders as $key => $value) {
        $value = preg_replace('!\r|\n!', '', $value);
        if (!$value) continue;
        $key = preg_replace('![^\x21-\x39\x3B-\x7e]!', '', $key);
        $userheader .= $key.': '.encode_1522_line_q(decode_utf8(rtrim($value), $encoding), 'n', $encoding).CRLF;
    }
    // Create Message ID
    if (!strstr($additional, 'Message-ID: <')) {
        $return .= create_msgid(isset($in['from']) ? $in['from'] : false);
    }

    $return .= 'Date: '.date('r').CRLF;
    if ($additional) {
        $return .= rtrim(preg_replace('!('.CRLF.')+!', CRLF, $additional)).CRLF;
    }
    // Default header lines
    if ($in['from']) {
        $return .= 'From: '.$in['from'].CRLF
                .'Return-Path: <'.mailparser::parse_email_address($in['from'], 0, false, true).'>'.CRLF;
    }
    if ($in['to']) $return .= 'To: '.$in['to'].CRLF;
    if ($in['cc']) $return .= 'Cc: '.$in['cc'].CRLF;
    if ($in['bcc']) $return .= 'Bcc: '.$in['bcc'].CRLF;
    if ($in['subject']) $return .= 'Subject: '.$in['subject'].CRLF;
    $return .= 'X-Mailer: phlyMail (http://phlymail.com)'.CRLF;
    // Put userspace header lines into mail header
    if ($userheader) {
        if ($uh_before) {
            $return = $userheader.$return;
        } else {
            $return .= $userheader;
        }
    }
    return $return;
}

// Create Message ID header
function create_msgid($from = false)
{
    if ($from) {
        $addi = mailparser::parse_email_address($from, 0, false, true);
        $dom = strstr($addi, '@');
    } elseif (isset($_SERVER['SERVER_NAME']) && $_SERVER['SERVER_NAME']) {
        $dom = '@'.$_SERVER['SERVER_NAME'];
    } else { // This is failsafe only
        $dom = '@phlymail.local';
    }
    return 'Message-ID: <'.uniqid(time().'.').$dom.'>'.CRLF;
}

/**
 * This function encodes hader line values, which may contain non 7bit characters
 * As of version 3.4.5 of this file base64 or QP encoding is automatically chosen by
 * looking for an amount of characters to encode which is more than about 1/3 of the
 * value length.
 * As of version 4.0.2 special care is taken to include spaces between encoded words
 * according to RFC 1522 (left out before due to misreading the RFC).
 *
 * @param string $coded The string to encode
 * @param string $cmode Pass 'g' for the whole string to encode, '@' for email addresses, otherwise
 *     the returned string will be encoded word by word (QP only)
 * @param string $encoding The character encoding the string is in
 * @return string
 */
function encode_1522_line_q($coded = '', $cmode = 'g', $encoding = 'iso-8859-1')
{
    preg_match_all('![^\t\x20\x2E\041-\074\076-\176]!', $coded, $found, PREG_SET_ORDER);
    if (sizeof($found) > strlen($coded)/3) {
        $chunklen = (isset($GLOBALS['_PM_']['core']['longsubjects'])) ? 988 : 76;
        $coded = chunk_split(base64_encode(rtrim($coded)), ($chunklen - strlen('=?'.$encoding.'?B??=')));
        $coded = str_replace('='.CRLF, '?='.CRLF.' =?'.$encoding.'?B?', trim($coded));
        $coded = '=?'.$encoding.'?B?'.$coded.'?='.CRLF;
        return rtrim($coded);
    }
    if ('g' == $cmode) {
        $chunklen = (isset($GLOBALS['_PM_']['core']['longsubjects'])) ? 988 : 76;
        $coded = str_replace('?', '=3F', phm_quoted_printable_encode(str_replace(' ', '_', rtrim($coded)), ($chunklen - strlen('=?'.$encoding.'?Q??='))));
        $coded = str_replace('='.CRLF, '?='.CRLF.' =?'.$encoding.'?Q?', trim($coded));
        $coded = '=?'.$encoding.'?Q?'.$coded.'?='.CRLF;
        return rtrim($coded);
    }
    if ('@' == $cmode) {
        $zeilen = explode(CRLF, $coded);
        $coded = '';
        foreach ($zeilen as $key => $value) {
            if (!$value) continue;
            if ($key > 0) $coded .= "\t";
            unset ($words);
            $words = explode(' ', $value, 2);
            foreach ($words as $k => $word) {
                if (preg_match('/[\x80-\xff]/', $word) && preg_match('/\(|\)/', $word)) {
                    $words[$k] = preg_replace
                            ('/^(\()?([^\)]+)(\))?/ie'
                            ,"'(=?".$encoding."?Q?'.rtrim(str_replace('?', '=3F', phm_quoted_printable_encode(str_replace(' ', '_', '\\2')))).'?=)'"
                            ,$word
                            );
                }
            }
            $coded .= str_replace('?= =?', '_?= =?', implode(' ', $words)).CRLF;
        }
        return rtrim($coded);
    } else {
        $zeilen = explode(CRLF, $coded);
        $coded = '';
        foreach ($zeilen as $key => $value) {
            if (!$value) continue;
            if ($key > 0) $coded .= "\t";
            unset ($words);
            $words = explode(' ', $value);
            foreach ($words as $k => $word) {
                if (preg_match('/[\x80-\xff]/', $word)) {
                    $words[$k] = '=?'.$encoding.'?Q?'.rtrim(str_replace('?', '=3F', phm_quoted_printable_encode(str_replace(' ', '_', $word)))).'?=';
                }
            }
            $coded .= str_replace('?= =?', '_?= =?', implode(' ', $words)).CRLF;
        }
        return rtrim($coded);
    }
}

function put_attach_stream(&$stream, $filename = '', $type = 'application/octet-stream', $name = 'unknown', $LE = CRLF)
{
    $type = trim($type);
    $name = basename(trim($name));
    $bytes_block = 57;

    // This should use the filename for finding the correct MIME type
    if ('application/octet-stream' == $type && 'unknown' != $name) {
        $ntype = $GLOBALS['MIME']->get_type_from_name($name, false);
        if ($ntype[0]) $type = $ntype[0];
    }
    $encoding = $GLOBALS['MIME']->get_encoding_from_type($type);
    $fh_src = fopen($filename, 'r');
    if ($fh_src) {
        $stream->put_data_to_stream('Content-Type: '.$type.'; name="'.$name.'"'.$LE);
        $stream->put_data_to_stream('Content-Disposition: attachment; filename="'.$name.'"'.$LE);
        switch ($encoding) {
        case 'q':
            $stream->put_data_to_stream('Content-Transfer-Encoding: quoted-printable'.$LE.$LE);
            while ($line = fgets($fh_src)) $stream->put_data_to_stream(phm_quoted_printable_encode($line));
            break;
        case '8':
        case '7':
            $stream->put_data_to_stream('Content-Transfer-Encoding: '.$encoding.'bit'.$LE.$LE);
            while ($line = fgets($fh_src)) $stream->put_data_to_stream($line);
            break;
        default:
            $stream->put_data_to_stream('Content-Transfer-Encoding: base64'.$LE.$LE);
            while ($line = fread($fh_src, $bytes_block)) $stream->put_data_to_stream(base64_encode($line).$LE);
            break;
        }
        fclose($fh_src);
        return true;
    } else return false;
}

function put_attach_file(&$file, $filename = '', $type = 'application/octet-stream', $name = 'unknown', $LE = CRLF)
{
    $type = trim($type);
    $name = basename(trim($name));
    $bytes_block = 57;

    // This should use the filename for finding the correct MIME type
    if ('application/octet-stream' == $type && 'unknown' != $name) {
        $ntype = $GLOBALS['MIME']->get_type_from_name($name, false);
        if ($ntype[0]) $type = $ntype[0];
    }
    $encoding = $GLOBALS['MIME']->get_encoding_from_type($type);
    $fh_src = fopen($filename, 'r');
    if ($fh_src) {
        fwrite($file, 'Content-Type: '.$type.'; name="'.$name.'"'.$LE);
        fwrite($file, 'Content-Disposition: attachment; filename="'.$name.'"'.$LE);
        switch ($encoding) {
        case 'q':
            fwrite($file, 'Content-Transfer-Encoding: quoted-printable'.$LE.$LE);
            while ($line = fgets($fh_src)) fwrite($file, phm_quoted_printable_encode($line));
            break;
        case '8':
        case '7':
            fwrite($file, 'Content-Transfer-Encoding: '.$encoding.'bit'.$LE.$LE);
            while ($line = fgets($fh_src)) fwrite($file, $line);
            break;
        default:
            fwrite($file, 'Content-Transfer-Encoding: base64'.$LE.$LE);
            while ($line = fread($fh_src, $bytes_block)) fwrite($file, base64_encode($line).$LE);
            break;
        }
        fclose($fh_src);
        return true;
    } else return false;
}

function set_prio_headers($return = '')
{
    switch ($return) {
    case '1':
        return 'X-Priority: 1'.CRLF.'Importance: High'.CRLF;
        break;
    case '3':
        return 'X-Priority: 3'.CRLF.'Importance: Normal'.CRLF;
        break;
    case '5':
        return 'X-Priority: 5'.CRLF.'Importance: Low'.CRLF;
        break;
    }
    return $return;
}

function gather_addresses($addresses)
{
    $address = implode(',', $addresses);
    $address = preg_replace('/,$/', '', preg_replace('/,+/', ',', $address));
    $duration = strlen($address);
    $mode = '';
    $j = 1;
    for ($i = 0; $i <= $duration; ++$i) {
        $test = substr($address, $i, 1);
        if ('comment' == $mode) {
            if (')' == $test)  {
                $mode = '';
                continue;
            }
        }
        if ('string' == $mode) {
            if ('"' == $test) {
                $mode = '';
                continue;
            }
        }
        if ('' == $mode) {
            if ('(' == $test) {
                $mode = 'comment';
                continue;
            }
            if ('"' == $test) {
                $mode = 'string';
                continue;
            }
            if (',' == $test) {
                $found[$j] = $i;
                $j++;
            }
        }
    }
    $found[0] = 0;
    $found[$j] = $duration;
    $return = '';
    for ($k = 0; $k < $j; ++$k) {
        $l = $k + 1;
        if (0 != $k) ++$found[$k];
        $build = substr($address, $found[$k], ($found[$l]-$found[$k]));
        $build = mailparser::parse_email_address($build, 0, true);
        if (0 != $k) $return .= ', ';
        $return .= $build[0];
    }
    return $return;
}

function email_check_validity($addresses)
{
    if (is_array($addresses) && !empty($addresses)) {
        $addresses = explode(', ', gather_addresses($addresses));
        foreach ($addresses as $k => $val) {
            if (!preg_match('!^[a-z0-9_\.]+\@[a-z0-9-\.]+\.[a-z]+$!i', $val)) {
                $return[] = $val;
                continue;
            }
            list(, $domain) = explode('@', $val, 2);
            if (getmxrr($domain, $mx, $weight) == 0) $return[] = $val;
        }
        return $return;
    }
}
?>
Return current item: phlyMail Lite