/**
* Secret Sauce - Transform an email string
* response to array key value format
*
* @param *string $email The actual email
* @param string|null $uniqueId The mail UID
* @param array $flags Any mail flags
*
* @return array
*/
private function getEmailFormat($email, $uniqueId = null, array $flags = array())
{
//if email is an array
if (is_array($email)) {
//make it into a string
$email = implode("\n", $email);
}
//split the head and the body
$parts = preg_split("/\n\\s*\n/", $email, 2);
$head = $parts[0];
$body = null;
if (isset($parts[1]) && trim($parts[1]) != ')') {
$body = $parts[1];
}
$lines = explode("\n", $head);
$head = array();
foreach ($lines as $line) {
if (trim($line) && preg_match("/^\\s+/", $line)) {
$head[count($head) - 1] .= ' ' . trim($line);
continue;
}
$head[] = trim($line);
}
$head = implode("\n", $head);
$recipientsTo = $recipientsCc = $recipientsBcc = $sender = array();
//get the headers
$headers1 = imap_rfc822_parse_headers($head);
$headers2 = $this->getHeaders($head);
//set the from
$sender['name'] = null;
if (isset($headers1->from[0]->personal)) {
$sender['name'] = $headers1->from[0]->personal;
//if the name is iso or utf encoded
if (preg_match("/^\\=\\?[a-zA-Z]+\\-[0-9]+.*\\?/", strtolower($sender['name']))) {
//decode the subject
$sender['name'] = str_replace('_', ' ', mb_decode_mimeheader($sender['name']));
}
}
$sender['email'] = $headers1->from[0]->mailbox . '@' . $headers1->from[0]->host;
//set the to
if (isset($headers1->to)) {
foreach ($headers1->to as $to) {
if (!isset($to->mailbox, $to->host)) {
continue;
}
$recipient = array('name' => null);
if (isset($to->personal)) {
$recipient['name'] = $to->personal;
//if the name is iso or utf encoded
if (preg_match("/^\\=\\?[a-zA-Z]+\\-[0-9]+.*\\?/", strtolower($recipient['name']))) {
//decode the subject
$recipient['name'] = str_replace('_', ' ', mb_decode_mimeheader($recipient['name']));
}
}
$recipient['email'] = $to->mailbox . '@' . $to->host;
$recipientsTo[] = $recipient;
}
}
//set the cc
if (isset($headers1->cc)) {
foreach ($headers1->cc as $cc) {
$recipient = array('name' => null);
if (isset($cc->personal)) {
$recipient['name'] = $cc->personal;
//if the name is iso or utf encoded
if (preg_match("/^\\=\\?[a-zA-Z]+\\-[0-9]+.*\\?/", strtolower($recipient['name']))) {
//decode the subject
$recipient['name'] = str_replace('_', ' ', mb_decode_mimeheader($recipient['name']));
}
}
$recipient['email'] = $cc->mailbox . '@' . $cc->host;
$recipientsCc[] = $recipient;
}
}
//set the bcc
if (isset($headers1->bcc)) {
foreach ($headers1->bcc as $bcc) {
$recipient = array('name' => null);
if (isset($bcc->personal)) {
$recipient['name'] = $bcc->personal;
//if the name is iso or utf encoded
if (preg_match("/^\\=\\?[a-zA-Z]+\\-[0-9]+.*\\?/", strtolower($recipient['name']))) {
//decode the subject
$recipient['name'] = str_replace('_', ' ', mb_decode_mimeheader($recipient['name']));
}
}
$recipient['email'] = $bcc->mailbox . '@' . $bcc->host;
$recipientsBcc[] = $recipient;
}
}
//.........这里部分代码省略.........
开发者ID:kamaroly,项目名称:Mail,代码行数:101,代码来源:Imap.php
示例7: _search
/**
* SEARCH IMAP
* @param Mixed $filter search filter as String or as Array of searches
* @param string $params option filter params
* @return mixed $data emails
*/
private function _search($filter = "ALL", $params = null)
{
if (is_array($filter)) {
$emails = array();
foreach ($filter as $string) {
$search = imap_search($this->imap, $string);
if ($search) {
$emails = array_merge($emails, $search);
}
}
} else {
$emails = imap_search($this->imap, $filter . " " . $params);
}
/* if emails are returned, cycle through each... */
$data = array();
if ($emails) {
/* for every email... */
foreach ($emails as $email_number) {
/* get information specific to this email */
$overview = imap_fetch_overview($this->imap, $email_number, 0);
$this->structure = imap_fetchstructure($this->imap, $email_number, 0);
/* commented out to speed up email retrieval */
$headers = imap_rfc822_parse_headers(imap_fetchheader($this->imap, $email_number));
switch (strtolower($this->structure->subtype)) {
case "plain":
$partNum = 1;
break;
case "alternative":
$partNum = 1;
break;
case "mixed":
$partNum = 1.2;
break;
case "html":
$partNum = 1.2;
break;
}
$partNum = 1;
$message = quoted_printable_decode(imap_fetchbody($this->imap, $email_number, $partNum, FT_PEEK));
/* get any possible attachments, commented out to speed up email retrieval, we do not want to do this unless we are automatically associating an email with a user */
// $attachments = $this->getAttachments($email_number);
$email = array('overview' => $overview[0], 'structure' => $this->structure, 'headers' => $headers, 'message' => $message);
$data[$email_number] = $email;
}
}
return $data;
}
/**
* Get message headers
*
* @return Message\Headers
*/
public function getHeaders()
{
if (null === $this->headers) {
$headers = imap_rfc822_parse_headers($this->getPlainHeader());
// check errors.
$lastError = imap_last_error();
if ($lastError !== false) {
if (1 === preg_match('/Unexpected characters at end of address: <(.*)>/', $lastError, $matches)) {
/**
* Message parsing from, to, cc headers exception occurs.
* It's not critical, because problem can be located just in single address from many.
* So we can proceed this letter, just drop the notice.
*/
imap_errors();
}
}
$this->headers = new Message\Headers($headers);
}
return $this->headers;
}
function getMessageHeader($_uid, $_partID = '')
{
$msgno = imap_msgno($this->mbox, $_uid);
if ($_partID == '') {
$retValue = imap_header($this->mbox, $msgno);
} else {
// do it the hard way
// we need to fetch the headers of another part(message/rfcxxxx)
$headersPart = imap_fetchbody($this->mbox, $_uid, $_partID . ".0", FT_UID);
$retValue = imap_rfc822_parse_headers($headersPart);
}
#_debug_array($retValue);
return $retValue;
}
/**
* Set member variable containing header information. Creates an array containing associative indices
* referring to various header information. Use {@link var_dump} or {@link print_r} on the {@link $header}
* member variable to view information gathered by this function.
*
* Returns header information on success and FALSE on failure.
*
* @param int &$mid message id
* @param string &$pid part id
* @param int $from_length (optional) from length for imap_headerinfo
* @param int $subject_length (optional) subject length for imap_headerinfo
* @param string $default_host (optional) default host for imap_headerinfo & imap_rfc822_parse_headers
* @param int $options (optional) flags/options for imap_fetchbody (DEPRECATED, use $this->option['fetchbody'])
* @return Array|BOOL
* @access public
* @see getParts
* @see imap_fetchheader
* @see imap_fetchbody
* @see imap_headerinfo
* @see imap_rfc822_parse_headers
*/
function getHeaders(&$mid, $pid = '0', $from_length = 1024, $subject_length = 1024, $default_host = NULL, $options = NULL)
{
if (FALSE === ($hpid = Mail_IMAP::getRawHeaders($mid, $pid, $options, FALSE))) {
return FALSE;
}
// $default_host contains the host information for addresses where it is not
// present. Specify it or attempt to use SERVER_NAME
if ($default_host == NULL && isset($_SERVER['SERVER_NAME']) && !empty($_SERVER['SERVER_NAME'])) {
$default_host = $_SERVER['SERVER_NAME'];
} else {
if ($default_host == NULL) {
$default_host = 'UNSPECIFIED-HOST-NAME';
}
}
// Parse the headers
$header_info = $hpid == '0' ? imap_headerinfo($this->mailbox, $mid, $from_length, $subject_length, $default_host) : imap_rfc822_parse_headers($this->rawHeaders[$mid], $default_host);
// Since individual member variable creation might create extra overhead,
// and having individual variables referencing this data and the original
// object would be too much as well, we'll just copy the object into an
// associative array, preform clean-up on those elements that require it,
// and destroy the original object after copying.
if (!is_object($header_info)) {
PEAR::raiseError('Mail_IMAP::getHeaders: Unable to retrieve header object, invalid part id: ' . $pid, NULL, PEAR_ERROR_TRIGGER, E_USER_WARNING);
return FALSE;
}
$headers = get_object_vars($header_info);
foreach ($headers as $key => $value) {
if (!is_object($value) && !is_array($value)) {
$this->header[$mid][$key] = $value;
}
}
// copy udate or create it from date string.
$this->header[$mid]['udate'] = isset($header_info->udate) && !empty($header_info->udate) ? $header_info->udate : strtotime($header_info->Date);
// clean up addresses
$line[] = 'from';
$line[] = 'reply_to';
$line[] = 'sender';
$line[] = 'return_path';
$line[] = 'to';
$line[] = 'cc';
$line[] = 'bcc';
for ($i = 0; $i < count($line); $i++) {
if (isset($header_info->{$line}[$i])) {
Mail_IMAP::_parseHeaderLine($mid, $header_info->{$line}[$i], $line[$i]);
}
}
// All possible information has been copied, destroy original object
unset($header_info);
return $this->header[$mid];
}
/**
* Takes the "parts" attribute of the object that imap_fetchbody() method
* returns, and recursively goes through looking for objects that have a
* disposition of "attachement" or "inline"
* @param int $msgNo The relative message number for the monitored mailbox
* @param object $parts Array of objects to examine
* @param string $emailId The GUID of the email saved prior to calling this method
* @param array $breadcrumb Default 0, build up of the parts mapping
* @param bool $forDisplay Default false
*/
function saveAttachments($msgNo, $parts, $emailId, $breadcrumb = '0', $forDisplay)
{
global $sugar_config;
/*
Primary body types for a part of a mail structure (imap_fetchstructure returned object)
0 => text
1 => multipart
2 => message
3 => application
4 => audio
5 => image
6 => video
7 => other
*/
foreach ($parts as $k => $part) {
$thisBc = $k + 1;
if ($breadcrumb != '0') {
$thisBc = $breadcrumb . '.' . $thisBc;
}
$attach = null;
// check if we need to recurse into the object
//if($part->type == 1 && !empty($part->parts)) {
if (isset($part->parts) && !empty($part->parts) && !(isset($part->subtype) && strtolower($part->subtype) == 'rfc822')) {
$this->saveAttachments($msgNo, $part->parts, $emailId, $thisBc, $forDisplay);
continue;
} elseif ($part->ifdisposition && strtolower($part->subtype) != 'rfc822') {
// we will take either 'attachments' or 'inline'
if (strtolower($part->disposition) == 'attachment' || strtolower($part->disposition) == 'inline' && $part->type != 0) {
$attach = $this->getNoteBeanForAttachment($emailId);
$fname = $this->handleEncodedFilename($this->retrieveAttachmentNameFromStructure($part));
if (!empty($fname)) {
//assign name to attachment
$attach->name = $fname;
} else {
//if name is empty, default to filename
$attach->name = urlencode($this->retrieveAttachmentNameFromStructure($part));
}
$attach->filename = $attach->name;
if (empty($attach->filename)) {
continue;
}
// deal with the MIME types email has
$attach->file_mime_type = $this->getMimeType($part->type, $part->subtype);
$attach->safeAttachmentName();
if ($forDisplay) {
$attach->id = $this->getTempFilename();
} else {
// only save if doing a full import, else we want only the binaries
$attach->save();
}
}
// end if disposition type 'attachment'
} elseif ($part->type == 2 && isset($part->subtype) && strtolower($part->subtype) == 'rfc822') {
$tmp_eml = imap_fetchbody($this->conn, $msgNo, $thisBc);
$rfcheaders = imap_rfc822_parse_headers($tmp_eml);
$attach = $this->getNoteBeanForAttachment($emailId);
$attach->file_mime_type = 'message/rfc822';
$attach->description = $tmp_eml;
$attach->filename = $attach->name = $rfcheaders->subject . ".eml";
$attach->safeAttachmentName();
if ($forDisplay) {
$attach->id = $this->getTempFilename();
} else {
// only save if doing a full import, else we want only the binaries
$attach->save();
}
} elseif (!$part->ifdisposition && $part->type != 1 && $part->type != 2 && $thisBc != '1') {
// No disposition here, but some IMAP servers lie about disposition headers, try to find the truth
// Also Outlook puts inline attachments as type 5 (image) without a disposition
if ($part->ifparameters) {
foreach ($part->parameters as $param) {
if (strtolower($param->attribute) == "name" || strtolower($param->attribute) == "filename") {
$fname = $this->handleEncodedFilename($param->value);
break;
}
}
if (empty($fname)) {
continue;
}
// we assume that named parts are attachments too
$attach = $this->getNoteBeanForAttachment($emailId);
$attach->filename = $attach->name = $fname;
$attach->file_mime_type = $this->getMimeType($part->type, $part->subtype);
$attach->safeAttachmentName();
if ($forDisplay) {
$attach->id = $this->getTempFilename();
} else {
// only save if doing a full import, else we want only the binaries
$attach->save();
}
//.........这里部分代码省略.........
/**
* Recupera o conjunto de cabeçalhos interpretados segundo a RFC-822
* @return stdClass
*/
public function getRFC822Headers() {
return (object) $this->parseHeaders( (array) imap_rfc822_parse_headers( $this->headers ) );
}
/**
* Set member variable containing header information. Creates an array containing
* associative indices referring to various header information. Use {@link var_dump}
* or {@link print_r} on the {@link $header} member variable to view information
* gathered by this function.
*
* If $ret is true, returns array containing header information on success and false
* on failure.
*
* If $ret is false, adds the header information to the $header member variable
* and returns BOOL.
*
* @param int &$mid message id
* @param string &$pid (optional) part id to retrieve headers for.
* @param bool $rtn
* (optional) If true return the headers, if false, assign to $header member variable.
*
* @param array $args
* (optional) Associative array containing extra arguments.
*
* $args['from_length'] int
* From field length for imap_headerinfo.
*
* $args['subject_length'] int
* Subject field length for imap_headerinfo
*
* $args['default_host'] string
* Default host for imap_headerinfo & imap_rfc822_parse_headers
*
* @return Array|BOOL
* @tutorial http://www.smilingsouls.net/Mail_IMAP?content=Mail_IMAP/getHeaders
* @access public
* @see getParts
* @see imap_fetchheader
* @see imap_fetchbody
* @see imap_headerinfo
* @see imap_rfc822_parse_headers
*/
function getHeaders(&$mid, $pid = '0', $rtn = false, $args = array())
{
$this->_checkIfParsed($mid);
if ($pid == $this->msg[$mid]['pid']) {
$pid = '0';
}
if ($pid !== '0') {
if (false === ($raw_headers = $this->getRawHeaders($mid, $pid, true, true))) {
return false;
}
if ($raw_headers === true) {
$pid = '0';
}
}
if (!isset($args['from_length'])) {
$args['from_length'] = 1024;
}
if (!isset($args['subject_length'])) {
$args['subject_length'] = 1024;
}
if (!isset($args['default_host'])) {
$args['default_host'] = null;
}
// Parse the headers
$header_info = $pid === '0' ? imap_headerinfo($this->mailbox, $mid, $args['from_length'], $args['subject_length'], $args['default_host']) : imap_rfc822_parse_headers($raw_headers, $args['default_host']);
// Since individual member variable creation might create extra overhead,
// and having individual variables referencing this data and the original
// object would be too much as well, we'll just copy the object into an
// associative array, preform clean-up on those elements that require it,
// and destroy the original object after copying.
if (!is_object($header_info)) {
$this->error->push(Mail_IMAPv2_ERROR_INVALID_PID, 'error', array('pid' => $pid));
return false;
}
$headers = get_object_vars($header_info);
foreach ($headers as $key => $value) {
if (!is_object($value) && !is_array($value)) {
// Decode all the headers using utf8_decode(imap_utf8())
$this->header[$mid][$key] = utf8_decode(imap_utf8($value));
}
}
// copy udate or create it from date string.
$this->header[$mid]['udate'] = isset($header_info->udate) && !empty($header_info->udate) ? $header_info->udate : strtotime($header_info->Date);
// clean up addresses
$line = array('from', 'reply_to', 'sender', 'return_path', 'to', 'cc', 'bcc');
for ($i = 0; $i < count($line); $i++) {
if (isset($header_info->{$line}[$i])) {
$this->_parseHeaderLine($mid, $header_info->{$line}[$i], $line[$i]);
}
}
// All possible information has been copied, destroy original object
unset($header_info);
return $rtn ? $this->header[$mid] : false;
}
请发表评论