/** * Returns the internal header array in array format. * * @param array $opts Optional parameters: * - canonical: (boolean) Use canonical (RFC 822/2045) line endings? * DEFAULT: Uses $this->_eol * - charset: (string) Encodes the headers using this charset. If empty, * encodes using internal charset (UTF-8). * DEFAULT: No encoding. * - defserver: (string) The default domain to append to mailboxes. * DEFAULT: No default name. * - nowrap: (integer) Don't wrap the headers. * DEFAULT: Headers are wrapped. * * @return array The headers in array format. */ public function toArray(array $opts = array()) { $address_keys = $this->addressFields(); $charset = array_key_exists('charset', $opts) ? empty($opts['charset']) ? 'UTF-8' : $opts['charset'] : null; $eol = empty($opts['canonical']) ? $this->_eol : "\r\n"; $mime = $this->mimeParamFields(); $ret = array(); foreach ($this->_headers as $header => $ob) { $val = is_array($ob['v']) ? $ob['v'] : array($ob['v']); foreach (array_keys($val) as $key) { if (in_array($header, $address_keys)) { /* Address encoded headers. */ $rfc822 = new Horde_Mail_Rfc822(); $text = $rfc822->parseAddressList($val[$key], array('default_domain' => empty($opts['defserver']) ? null : $opts['defserver']))->writeAddress(array('encode' => $charset, 'idn' => true)); } elseif (in_array($header, $mime) && !empty($ob['p'])) { /* MIME encoded headers (RFC 2231). */ $text = $val[$key]; foreach ($ob['p'] as $name => $param) { foreach (Horde_Mime::encodeParam($name, $param, array('charset' => $charset, 'escape' => true)) as $name2 => $param2) { $text .= '; ' . $name2 . '=' . $param2; } } } else { $text = is_null($charset) ? $val[$key] : Horde_Mime::encode($val[$key], $charset); } if (empty($opts['nowrap'])) { /* Remove any existing linebreaks and wrap the line. */ $header_text = $ob['h'] . ': '; $text = ltrim(substr(wordwrap($header_text . strtr(trim($text), array("\r" => '', "\n" => '')), 76, $eol . ' '), strlen($header_text))); } $val[$key] = $text; } $ret[$ob['h']] = count($val) == 1 ? reset($val) : $val; } return $ret; }
/** */ protected function _sendEncode($opts) { return array(Horde_Mime::encode($this->value, $opts['charset'])); }
/** */ protected function _writeAddress($opts) { $rfc822 = new Horde_Mail_Rfc822(); $address = $rfc822->encode($this->mailbox, 'address'); $host = empty($opts['idn']) ? $this->host : $this->host_idn; if (strlen($host)) { $address .= '@' . $host; } $personal = $this->personal; if (strlen($personal)) { if (!empty($opts['encode'])) { $personal = Horde_Mime::encode($this->personal, $opts['encode']); } if (empty($opts['noquote'])) { $personal = $rfc822->encode($personal, 'personal'); } } if (!empty($opts['comment']) && !empty($this->comment)) { foreach ($this->comment as $val) { $personal .= ' (' . $rfc822->encode($val, 'comment') . ')'; } } return strlen($personal) && $personal != $address ? ltrim($personal) . ' <' . $address . '>' : $address; }
/** * Constructs a new procmail recipe. * * @param array $params Array of parameters. * REQUIRED FIELDS: * 'action' * OPTIONAL FIELDS: * 'action-value' (only used if the * 'action' requires it) * 'disable' * @param array $scriptparams Array of parameters passed to * Ingo_Script_Procmail. */ public function __construct($params = array(), $scriptparams = array()) { $this->_disable = !empty($params['disable']); $this->_params = array_merge($this->_params, $scriptparams); $delivery = '| '; if (isset($this->_params['delivery_agent'])) { $delivery .= $this->_params['delivery_agent'] . ' '; } if (isset($this->_params['delivery_mailbox_prefix'])) { $delivery .= ' ' . $this->_params['delivery_mailbox_prefix']; } switch ($params['action']) { case 'Ingo_Rule_User_Keep': // Note: you may have to set the DEFAULT variable in your // backend configuration. $this->_action[] = $delivery .= '$DEFAULT'; break; case 'Ingo_Rule_User_Move': $this->_action[] = $delivery .= $this->procmailPath($params['action-value']); break; case 'Ingo_Rule_User_Discard': $this->_action[] = '/dev/null'; break; case 'Ingo_Rule_User_Redirect': $this->_action[] = '! ' . $params['action-value']; break; case 'Ingo_Rule_User_RedirectKeep': $this->_action[] = '{'; $this->_action[] = ' :0 c'; $this->_action[] = ' ! ' . $params['action-value']; if (strpos($this->_flags, 'c') === false) { $this->_action[] = ''; $this->_action[] = ' :0' . (isset($this->_params['delivery_agent']) ? ' w' : ''); $this->_action[] = ' ' . $delivery . '$DEFAULT'; } $this->_action[] = '}'; break; case 'Ingo_Rule_User_Reject': $this->_action[] = '{'; $this->_action[] = ' :0 h'; $this->_action[] = ' SUBJECT=| formail -xSubject:'; $this->_action[] = ''; $this->_action[] = ' :0 h'; $this->_action[] = ' SENDER=| formail -zxFrom:'; $this->_action[] = ''; $this->_action[] = ' :0 Wh'; $this->_action[] = ' * !^FROM_DAEMON'; $this->_action[] = ' * !^X-Loop: $SENDER'; $this->_action[] = ' | (formail -rA"X-Loop: $SENDER" \\'; $reason = $params['action-value']; if (Horde_Mime::is8bit($reason)) { $this->_action[] = ' -i"Subject: Re: $SUBJECT" \\'; $this->_action[] = ' -i"Content-Transfer-Encoding: quoted-printable" \\'; $this->_action[] = ' -i"Content-Type: text/plain; charset=UTF-8" ; \\'; $reason = Horde_Mime_QuotedPrintable::encode($reason); } else { $this->_action[] = ' -i"Subject: Re: $SUBJECT" ; \\'; } $reason = addcslashes($reason, "\\\n\r\t\"`"); $this->_action[] = ' ' . $this->_params['echo'] . ' -e "' . $reason . '" \\'; $this->_action[] = ' ) | $SENDMAIL -oi -t'; $this->_action[] = '}'; break; case 'Ingo_Rule_System_Vacation': $days = $params['action-value']['days']; $timed = !empty($params['action-value']['start']) && !empty($params['action-value']['end']); $this->_action[] = '{'; foreach ($params['action-value']['addresses'] as $address) { if (empty($address)) { continue; } $this->_action[] = ' :0'; $this->_action[] = ' * ^TO_' . $address; $this->_action[] = ' {'; $this->_action[] = ' FILEDATE=`test -f ${VACATION_DIR:-.}/\'.vacation.' . $address . '\' && ' . $this->_params['ls'] . ' -lcn --time-style=+%s ${VACATION_DIR:-.}/\'.vacation.' . $address . '\' | ' . 'awk \'{ print $6 + (' . $days * 86400 . ') }\'`'; $this->_action[] = ' DATE=`' . $this->_params['date'] . ' +%s`'; $this->_action[] = ' DUMMY=`test -f ${VACATION_DIR:-.}/\'.vacation.' . $address . '\' && ' . 'test $FILEDATE -le $DATE && ' . 'rm ${VACATION_DIR:-.}/\'.vacation.' . $address . '\'`'; if ($timed) { $this->_action[] = ' START=' . $params['action-value']['start']; $this->_action[] = ' END=' . $params['action-value']['end']; } $this->_action[] = ''; $this->_action[] = ' :0 h'; $this->_action[] = ' SUBJECT=| formail -xSubject:'; $this->_action[] = ''; $this->_action[] = ' :0 Whc: ${VACATION_DIR:-.}/vacation.lock'; if ($timed) { $this->_action[] = ' * ? test $DATE -gt $START && test $END -gt $DATE'; } $this->_action[] = ' {'; $this->_action[] = ' :0 Wh'; $this->_action[] = ' * ^TO_' . $address; $this->_action[] = ' * !^X-Loop: ' . $address; $this->_action[] = ' * !^X-Spam-Flag: YES'; if (count($params['action-value']['excludes']) > 0) { foreach ($params['action-value']['excludes'] as $exclude) { if (!empty($exclude)) { $this->_action[] = ' * !^From.*' . $exclude; } } } if ($params['action-value']['ignorelist']) { $this->_action[] = ' * !^FROM_DAEMON'; } $this->_action[] = ' | formail -rD 8192 ${VACATION_DIR:-.}/.vacation.' . $address; $this->_action[] = ' :0 eh'; $this->_action[] = ' | (formail -rI"Precedence: junk" \\'; $this->_action[] = ' -a"From: <' . $address . '>" \\'; $this->_action[] = ' -A"X-Loop: ' . $address . '" \\'; $reason = Ingo_Rule_System_Vacation::vacationReason($params['action-value']['reason'], $params['action-value']['start'], $params['action-value']['end']); if (Horde_Mime::is8bit($reason)) { $this->_action[] = ' -i"Subject: ' . Horde_Mime::encode($params['action-value']['subject'] . ' (Re: $SUBJECT)') . '" \\'; $this->_action[] = ' -i"Content-Transfer-Encoding: quoted-printable" \\'; $this->_action[] = ' -i"Content-Type: text/plain; charset=UTF-8" ; \\'; $reason = Horde_Mime_QuotedPrintable::encode($reason); } else { $this->_action[] = ' -i"Subject: ' . Horde_Mime::encode($params['action-value']['subject'] . ' (Re: $SUBJECT)') . '" ; \\'; } $reason = addcslashes($reason, "\\\n\r\t\"`"); $this->_action[] = ' ' . $this->_params['echo'] . ' -e "' . $reason . '" \\'; $this->_action[] = ' ) | $SENDMAIL -f' . $address . ' -oi -t'; $this->_action[] = ' }'; $this->_action[] = ' }'; } $this->_action[] = '}'; break; case 'Ingo_Rule_System_Forward': /* Make sure that we prevent mail loops using 3 methods. * * First, we call sendmail -f to set the envelope sender to be the * same as the original sender, so bounces will go to the original * sender rather than to us. This unfortunately triggers lots of * Authentication-Warning: messages in sendmail's logs. * * Second, add an X-Loop header, to handle the case where the * address we forward to forwards back to us. * * Third, don't forward mailer daemon messages (i.e., bounces). * Method 1 above should make this redundant, unless we're sending * mail from this account and have a bad forward-to account. * * Get the from address, saving a call to formail if possible. * The procmail code for doing this is borrowed from the * Procmail Library Project, http://pm-lib.sourceforge.net/. * The Ingo project has the permission to use Procmail Library code * under Apache licence v 1.x or any later version. * Permission obtained 2006-04-04 from Author Jari Aalto. */ $this->_action[] = '{'; $this->_action[] = ' :0 '; $this->_action[] = ' *$ ! ^From *\\/[^ ]+'; $this->_action[] = ' *$ ! ^Sender: *\\/[^ ]+'; $this->_action[] = ' *$ ! ^From: *\\/[^ ]+'; $this->_action[] = ' *$ ! ^Reply-to: *\\/[^ ]+'; $this->_action[] = ' {'; $this->_action[] = ' OUTPUT = `formail -zxFrom:`'; $this->_action[] = ' }'; $this->_action[] = ' :0 E'; $this->_action[] = ' {'; $this->_action[] = ' OUTPUT = $MATCH'; $this->_action[] = ' }'; $this->_action[] = ''; /* Forward to each address on our list. */ foreach ($params['action-value'] as $address) { if (!empty($address)) { $this->_action[] = ' :0 c'; $this->_action[] = ' * !^FROM_MAILER'; $this->_action[] = ' * !^X-Loop: to-' . $address; $this->_action[] = ' | formail -A"X-Loop: to-' . $address . '" | $SENDMAIL -oi -f $OUTPUT ' . $address; } } /* In case of mail loop or bounce, store a copy locally. Note * that if we forward to more than one address, only a mail loop * on the last address will cause a local copy to be saved. TODO: * The next two lines are redundant (and create an extra copy of * the message) if "Keep a copy of messages in this account" is * checked. */ $this->_action[] = ' :0 E' . (isset($this->_params['delivery_agent']) ? 'w' : ''); $this->_action[] = ' ' . $delivery . '$DEFAULT'; $this->_action[] = ' :0 '; $this->_action[] = ' /dev/null'; $this->_action[] = '}'; break; default: $this->_valid = false; break; } }
/** * Unserialize data. * * @param mixed $data The data to be unserialized. * @param mixed $mode The mode of unserialization. Can be either a * single mode or array of modes. If array, will be * unserialized in the order provided. * @param mixed $params Any additional parameters the unserialization * method requires. * * @return mixed Unserialized data. * @throws Horde_Serialize_Exception */ protected static function _unserialize(&$data, $mode, $params = null) { switch ($mode) { case self::NONE: break; case self::RAW: $data = rawurldecode($data); break; case self::URL: $data = urldecode($data); break; case self::WDDX: $data = wddx_deserialize($data); break; case self::BZIP: // $params['small'] = Use bzip2 'small memory' mode? $data = bzdecompress($data, isset($params['small']) ? $params['small'] : false); break; case self::IMAP8: $data = quoted_printable_decode($data); break; case self::IMAPUTF7: $data = Horde_String::convertCharset(Horde_Imap_Client_Utf7imap::Utf7ImapToUtf8($data), 'UTF-8', 'ISO-8859-1'); break; case self::IMAPUTF8: $data = Horde_Mime::encode($data); break; case self::BASIC: $data2 = @unserialize($data); // Unserialize can return false both on error and if $data is the // false value. if ($data2 === false && $data == serialize(false)) { return $data2; } $data = $data2; break; case self::GZ_DEFLATE: $data = gzinflate($data); break; case self::BASE64: $data = base64_decode($data); break; case self::GZ_COMPRESS: $data = gzuncompress($data); break; // $params = Output character set // $params = Output character set case self::UTF7: $data = Horde_String::convertCharset($data, 'utf-7', $params); break; // $params = Output character set // $params = Output character set case self::UTF7_BASIC: $data = self::unserialize($data, array(self::BASIC, self::UTF7), $params); break; case self::JSON: $out = json_decode($data); if (!is_null($out) || strcasecmp($data, 'null') === 0) { return $out; } break; case self::LZF: $data = @lzf_decompress($data); break; } if ($data === false) { throw new Horde_Serialize_Exception('Unserialization failed.'); } return $data; }
/** */ protected function _vacationCode() { $code = 'vacation :days ' . $this->_vars['days'] . ' '; $addresses = $this->_vars['addresses']; $stringlist = ''; if (count($addresses) > 1) { foreach ($addresses as $address) { $address = trim($address); if (!empty($address)) { $stringlist .= empty($stringlist) ? '"' : ', "'; $stringlist .= Ingo_Script_Sieve::escapeString($address) . '"'; } } $stringlist = "[" . $stringlist . "] "; } elseif (count($addresses) == 1) { $stringlist = '"' . Ingo_Script_Sieve::escapeString($addresses[0]) . '" '; } if (!empty($stringlist)) { $code .= ':addresses ' . $stringlist; } if (!empty($this->_vars['subject'])) { $code .= ':subject "' . Horde_Mime::encode(Ingo_Script_Sieve::escapeString($this->_vars['subject'])) . '" '; } return $code . '"' . Ingo_Script_Sieve::escapeString(Ingo_Script_Util::vacationReason($this->_vars['reason'], $this->_vars['start'], $this->_vars['end'])) . '";'; }
/** */ protected function _writeAddress($opts) { $addr = $this->addresses->writeAddress($opts); $groupname = $this->groupname; if (!empty($opts['encode'])) { $groupname = Horde_Mime::encode($groupname, $opts['encode']); } $rfc822 = new Horde_Mail_Rfc822(); return $rfc822->encode($groupname, 'personal') . ':' . (strlen($addr) ? ' ' . $addr : '') . ';'; }
/** * @see encode() */ protected function _encode($name, $val, $opts) { $curr = 0; $encode = $wrap = false; $out = array(); // 2 = '=', ';' $pre_len = strlen($name) + 2; /* Several possibilities: * - String is ASCII. Output as ASCII (duh). * - Language information has been provided. We MUST encode output * to include this information. * - String is non-ASCII, but can losslessly translate to ASCII. * Output as ASCII (most efficient). * - String is in non-ASCII, but doesn't losslessly translate to * ASCII. MUST encode output (duh). */ if (empty($opts['lang']) && !Horde_Mime::is8bit($val, 'UTF-8')) { $string = $val; } else { $cval = Horde_String::convertCharset($val, 'UTF-8', $opts['charset']); $string = Horde_String::lower($opts['charset']) . '\'' . (empty($opts['lang']) ? '' : Horde_String::lower($opts['lang'])) . '\'' . rawurlencode($cval); $encode = true; /* Account for trailing '*'. */ ++$pre_len; } if ($pre_len + strlen($string) > 75) { /* Account for continuation '*'. */ ++$pre_len; $wrap = true; while ($string) { $chunk = 75 - $pre_len - strlen($curr); $pos = min($chunk, strlen($string) - 1); /* Don't split in the middle of an encoded char. */ if ($chunk == $pos && $pos > 2) { for ($i = 0; $i <= 2; ++$i) { if ($string[$pos - $i] == '%') { $pos -= $i + 1; break; } } } $lines[] = substr($string, 0, $pos + 1); $string = substr($string, $pos + 1); ++$curr; } } else { $lines = array($string); } foreach ($lines as $i => $line) { $out[$name . ($wrap ? '*' . $i : '') . ($encode ? '*' : '')] = $line; } if (!empty($opts['broken_rfc2231']) && !isset($out[$name])) { $out = array_merge(array($name => Horde_Mime::encode($val, $opts['charset'])), $out); } /* Escape characters in params (See RFC 2045 [Appendix A]). * Must be quoted-string if one of these exists. */ return $this->_escapeParams($out); }
/** */ protected function _writeAddress($opts) { $rfc822 = new Horde_Mail_Rfc822(); $address = $rfc822->encode($this->mailbox, 'address'); $host = empty($opts['idn']) ? $this->host : $this->host_idn; if (strlen($host)) { $address .= '@' . $host; } $personal = $this->personal; if (strlen($personal)) { if (!empty($opts['encode'])) { $personal = Horde_Mime::encode($this->personal, $opts['encode']); } $personal = $rfc822->encode($personal, 'personal'); } return strlen($personal) && $personal != $address ? $personal . ' <' . $address . '>' : $address; }
public function testNullCharacterInEncodeOutput() { $this->assertEquals('=?utf-16le?b?AAA=?=', Horde_Mime::encode("", 'UTF-16LE')); }
/** * @dataProvider encodeProvider */ public function testEncode($data, $charset, $expected) { $this->assertEquals($expected, Horde_Mime::encode($data, $charset)); }
/** * Constructs a new maildrop recipe. * * @param array $params Array of parameters. * REQUIRED FIELDS: * 'action' * OPTIONAL FIELDS: * 'action-value' (only used if the * 'action' requires it) * 'combine' * 'disable' * @param array $scriptparams Array of parameters passed to * Ingo_Script_Maildrop::. */ public function __construct($params = array(), $scriptparams = array()) { $this->_disable = !empty($params['disable']); $this->_params = $scriptparams; $this->_action[] = 'exception {'; switch ($params['action']) { case 'Ingo_Rule_User_Keep': $this->_action[] = ' to "${DEFAULT}"'; break; case 'Ingo_Rule_User_Move': $this->_action[] = ' to ' . $this->maildropPath($params['action-value']); break; case 'Ingo_Rule_User_Discard': $this->_action[] = ' exit'; break; case 'Ingo_Rule_User_Redirect': $this->_action[] = ' to "! ' . $params['action-value'] . '"'; break; case 'Ingo_Rule_User_RedirectKeep': $this->_action[] = ' cc "! ' . $params['action-value'] . '"'; $this->_action[] = ' to "${DEFAULT}"'; break; case 'Ingo_Rule_User_Reject': // EX_NOPERM (permanent failure) $this->_action[] = ' EXITCODE=77'; $this->_action[] = ' echo "5.7.1 ' . $params['action-value'] . '"'; $this->_action[] = ' exit'; break; case 'Ingo_Rule_System_Vacation': $from = reset($params['action-value']['addresses']); /* Exclusion of addresses from vacation */ if ($params['action-value']['excludes']) { $exclude = implode('|', $params['action-value']['excludes']); // Disable wildcard until officially supported. // $exclude = str_replace('*', '(.*)', $exclude); $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^From:.*(' . $exclude . ')/')); } $start = strftime($params['action-value']['start']); if ($start === false) { $start = 0; } $end = strftime($params['action-value']['end']); if ($end === false) { $end = 0; } $days = strftime($params['action-value']['days']); if ($days === false) { // Set to same value as $_days in ingo/lib/Storage.php $days = 7; } // Rule : Do not send responses to bulk or list messages if ($params['action-value']['ignorelist'] == 1) { $params['combine'] = Ingo_Rule_User::COMBINE_ALL; $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Precedence: (bulk|list|junk)/')); $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Return-Path:.*<#@\\[\\]>/')); $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Return-Path:.*<>/')); $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^From:.*MAILER-DAEMON/')); $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^X-ClamAV-Notice-Flag: *YES/')); $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Content-Type:.*message\\/delivery-status/')); $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Subject:.*Delivery Status Notification/')); $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Subject:.*Undelivered Mail Returned to Sender/')); $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Subject:.*Delivery failure/')); $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Subject:.*Message delay/')); $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Subject:.*Mail Delivery Subsystem/')); $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Subject:.*Mail System Error.*Returned Mail/')); $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^X-Spam-Flag: YES/ ')); } else { $this->addCondition(array('field' => 'From', 'value' => '')); } // Rule : Start/End of vacation if ($start != 0 && $end !== 0) { $this->_action[] = ' flock "$HOME/vacationprocess.lock" {'; $this->_action[] = ' current_time=time'; $this->_action[] = ' if ( \\ '; $this->_action[] = ' ($current_time >= ' . $start . ') && \\ '; $this->_action[] = ' ($current_time <= ' . $end . ')) '; $this->_action[] = ' {'; } $this->_action[] = ' cc "' . str_replace('"', '\\"', sprintf('| mailbot %s -D %d -c \'UTF-8\' -t $HOME/vacation.msg -d $HOME/vacation -A %s -s %s /usr/sbin/sendmail -t -f %s', $this->_params['mailbotargs'], $params['action-value']['days'], escapeshellarg('From: ' . $from), escapeshellarg(Horde_Mime::encode($params['action-value']['subject'])), escapeshellarg($from))) . '"'; if ($start != 0 && $end !== 0) { $this->_action[] = ' }'; $this->_action[] = ' }'; } break; case 'Ingo_Rule_System_Forward': case Ingo_Script_Maildrop::MAILDROP_STORAGE_ACTION_STOREANDFORWARD: foreach ($params['action-value'] as $address) { if (!empty($address)) { $this->_action[] = ' cc "! ' . $address . '"'; } } /* The 'to' must be the last action, because maildrop * stops processing after it. */ if ($params['action'] == Ingo_Script_Maildrop::MAILDROP_STORAGE_ACTION_STOREANDFORWARD) { $this->_action[] = ' to "${DEFAULT}"'; } else { $this->_action[] = ' exit'; } break; default: $this->_valid = false; break; } $this->_action[] = '}'; if (isset($params['combine']) && $params['combine'] == Ingo_Rule_User::COMBINE_ALL) { $this->_combine = '&& '; } else { $this->_combine = '|| '; } }
/** */ protected function _writeAddress($opts) { $addr = $this->addresses->writeAddress($opts); $groupname = $this->groupname; if (!empty($opts['encode'])) { $groupname = Horde_Mime::encode($groupname, $opts['encode']); } if (empty($opts['noquote'])) { $rfc822 = new Horde_Mail_Rfc822(); $groupname = $rfc822->encode($groupname, 'personal'); } if (!empty($opts['comment']) && !empty($this->comment)) { $rfc822 = new Horde_Mail_Rfc822(); foreach ($this->comment as $val) { $personal .= ' (' . $rfc822->encode($val, 'comment') . ')'; } } return ltrim($groupname) . ':' . (strlen($addr) ? ' ' . $addr : '') . ';'; }