Add imap and authimap support
git-svn-id: https://svn.fournier38.fr/svn/ProgSVN/trunk@2370 bf3deb0d-5f1a-0410-827f-c0cc1f45334c
This commit is contained in:
83
authimap.php
Normal file
83
authimap.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/** DomFramework
|
||||
@package domframework
|
||||
@author Dominique Fournier <dominique@fournier38.fr> */
|
||||
|
||||
require_once ("domframework/auth.php");
|
||||
require_once ("domframework/imap.php");
|
||||
|
||||
/** User authentication against IMAP server */
|
||||
class authimap extends auth
|
||||
{
|
||||
/** IMAP server */
|
||||
public $imapServer = "localhost";
|
||||
/** IMAP TCP port (143 by default) */
|
||||
public $imapPort = 143;
|
||||
/** IMAP SSL connection */
|
||||
public $imapSSL = false;
|
||||
/** IMAP SSL CheckCertificate */
|
||||
public $imapSSLCheckCertificates = true;
|
||||
|
||||
/** Check the availablity of the IMAP support in PHP */
|
||||
function __construct ()
|
||||
{
|
||||
if (!function_exists ("imap_open"))
|
||||
throw new Exception ("IMAP support unavailable in PHP", 500);
|
||||
}
|
||||
|
||||
/** Establish the connection to IMAP server. Don't do anything as the
|
||||
needed parameters are username and password */
|
||||
public function connect ()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
/** Try to authenticate the email/password of the user
|
||||
@param string $email Email to authenticate
|
||||
@param string $password Password to authenticate */
|
||||
public function authentication ($email, $password)
|
||||
{
|
||||
$imap = new imap ($this->imapServer, $this->imapPort,
|
||||
$email, $password,
|
||||
$this->imapSSL, $this->imapSSLCheckCertificates);
|
||||
// Let the throw Exception be catched by the parent
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Return all the parameters recorded for the authenticate user */
|
||||
public function getdetails ()
|
||||
{
|
||||
throw new Exception (dgettext("domframework",
|
||||
"Can't get details for IMAP users"), 405);
|
||||
}
|
||||
|
||||
/** Method to change the password
|
||||
@param string $oldpassword The old password (to check if the user have the
|
||||
rights to change the password)
|
||||
@param string $newpassword The new password to be recorded */
|
||||
public function changepassword ($oldpassword, $newpassword)
|
||||
{
|
||||
throw new Exception (dgettext("domframework",
|
||||
"The password can't be change for IMAP users"), 405);
|
||||
}
|
||||
|
||||
/** Method to overwrite the password (without oldpassword check)
|
||||
Must be reserved to the administrators. For the users, use changepassword
|
||||
method
|
||||
@param string $email the user identifier to select
|
||||
@param string $newpassword The new password to be recorded */
|
||||
public function overwritepassword ($email, $newpassword)
|
||||
{
|
||||
throw new exception (dgettext("domframework",
|
||||
"The password can't be overwrite for IMAP users"),
|
||||
405);
|
||||
}
|
||||
|
||||
/** List all the users available in the database
|
||||
Return firstname, lastname, mail, with mail is an array */
|
||||
public function listusers ()
|
||||
{
|
||||
throw new Exception (dgettext("domframework",
|
||||
"Can't get list of users for IMAP server"), 405);
|
||||
}
|
||||
}
|
||||
677
imap.php
Normal file
677
imap.php
Normal file
@@ -0,0 +1,677 @@
|
||||
<?php
|
||||
/** DomFramework
|
||||
@package domframework
|
||||
@author Dominique Fournier <dominique@fournier38.fr> */
|
||||
|
||||
/** IMAP connection abstraction
|
||||
In the IMAP terminology, "mailbox" is a folder in the mailbox of the user */
|
||||
class imap
|
||||
{
|
||||
/** The mailbox string */
|
||||
private $mailbox;
|
||||
/** The current folder in UTF-8 */
|
||||
private $curDir = "INBOX";
|
||||
/** The auto expunge feature, after deleting/moving an email */
|
||||
public $autoexpunge = true;
|
||||
|
||||
/** Limit to one instance of the connection to the same database */
|
||||
// Based on an idea of http://tonylandis.com/php/php5-pdo-singleton-class/
|
||||
private static $instance = array ();
|
||||
|
||||
/** The constructor
|
||||
The IMAP standard port is 143, but tunnelled is 993 */
|
||||
public function __construct ($imapserver = "localhost", $imapport = 143,
|
||||
$username = null, $password = null,
|
||||
$imapssl = false, $imapcertvalidate = true)
|
||||
{
|
||||
if (! function_exists ("imap_open"))
|
||||
throw new Exception ("PHP don't support IMAP. Please add it !", 500);
|
||||
if (! function_exists ("mb_convert_encoding"))
|
||||
throw new Exception ("PHP don't support MBString. Please add it !", 500);
|
||||
if ($username === null)
|
||||
throw new Exception ("No username provided for IMAP server", 500);
|
||||
if ($password === null)
|
||||
throw new Exception ("No password provided for IMAP server", 500);
|
||||
$imapssl = ($imapssl !== false) ? "/ssl" : "";
|
||||
$imapcertvalidate = ($imapcertvalidate !== false) ? "/novalidate-cert" : "";
|
||||
$this->mailbox = "{"."$imapserver:$imapport/imap$imapssl$imapcertvalidate".
|
||||
"/user=$username}";
|
||||
if (! array_key_exists ($this->mailbox, self::$instance))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Timeout authentication error to 1s (can't be less). By default, IMAP
|
||||
// wait 10s before returning an auth error
|
||||
imap_timeout (IMAP_READTIMEOUT, 1);
|
||||
self::$instance[$this->mailbox] = @imap_open ($this->mailbox, $username,
|
||||
$password);
|
||||
if (self::$instance[$this->mailbox] === FALSE)
|
||||
throw new Exception (imap_last_error());
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// imap_errors() takes the errors and clear the error stack
|
||||
$errors = imap_errors();
|
||||
throw new Exception ("IMAP error : ".$e->getMessage(), 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////
|
||||
/// FOLDERS ///
|
||||
///////////////////
|
||||
/** Return an array of the existing folders. The sub-folders are with slash
|
||||
separator
|
||||
The names of folders are converted in UTF-8 */
|
||||
public function foldersList ()
|
||||
{
|
||||
$list = array_keys ($this->foldersListWithAttr ());
|
||||
natsort ($list);
|
||||
return $list;
|
||||
}
|
||||
|
||||
/** Return an array with folder name in key and attributes in value. The
|
||||
attributes allow to see if there is new mails in folders */
|
||||
public function foldersListWithAttr ()
|
||||
{
|
||||
$list = imap_getmailboxes (self::$instance[$this->mailbox], $this->mailbox,
|
||||
"*");
|
||||
$res = array ();
|
||||
foreach ($list as $val)
|
||||
{
|
||||
$dir = substr ($val->name, strlen ($this->mailbox));
|
||||
$dir = mb_convert_encoding ($dir, "UTF8", "UTF7-IMAP");
|
||||
if (isset ($val->delimiter))
|
||||
$dir = str_replace ($val->delimiter, "/", $dir);
|
||||
$res[$dir] = $val->attributes;
|
||||
}
|
||||
return ($res);
|
||||
}
|
||||
|
||||
/** Change to provided folder
|
||||
The folder name must be in UTF-8. The folder must be absolute */
|
||||
public function changeFolder ($folder)
|
||||
{
|
||||
if (! in_array ($folder, $this->foldersList ()))
|
||||
throw new Exception ("Folder not found", 404);
|
||||
$folderUTF7 = mb_convert_encoding ($folder, "UTF7-IMAP","UTF-8");
|
||||
$rc = @imap_reopen (self::$instance[$this->mailbox],
|
||||
$this->mailbox.$folderUTF7);
|
||||
if ($rc === true)
|
||||
$this->curDir = $folder;
|
||||
else
|
||||
throw new Exception ("Can't go in provided folder", 500);
|
||||
return $rc;
|
||||
}
|
||||
|
||||
/** Return the current folder in UTF-8 */
|
||||
public function getFolder ()
|
||||
{
|
||||
return $this->curDir;
|
||||
}
|
||||
|
||||
/** Create a new folder, provided in UTF-8. The folder must be absolute */
|
||||
public function createFolder ($folder)
|
||||
{
|
||||
if ( in_array ($folder, $this->foldersList ()))
|
||||
throw new Exception ("Folder already exists", 406);
|
||||
$folderUTF7 = mb_convert_encoding ($folder, "UTF7-IMAP","UTF-8");
|
||||
return imap_createmailbox (self::$instance[$this->mailbox],
|
||||
$this->mailbox.$folderUTF7);
|
||||
}
|
||||
|
||||
/** Delete an existing folder provided in UTF-8. The folder must be absolute
|
||||
*/
|
||||
public function deleteFolder ($folder)
|
||||
{
|
||||
if (! in_array ($folder, $this->foldersList ()))
|
||||
throw new Exception ("Folder not found", 404);
|
||||
$folderUTF7 = mb_convert_encoding ($folder, "UTF7-IMAP","UTF-8");
|
||||
return imap_deletemailbox (self::$instance[$this->mailbox],
|
||||
$this->mailbox.$folderUTF7);
|
||||
}
|
||||
|
||||
/** Return the list of the folders substcribed by the user. The folders are
|
||||
in UTF-8 */
|
||||
public function getSubscribe ()
|
||||
{
|
||||
$subs = imap_getsubscribed (self::$instance[$this->mailbox], $this->mailbox,
|
||||
"*");
|
||||
$res = array ();
|
||||
foreach ($subs as $sub)
|
||||
{
|
||||
$res [] = str_replace ($sub->delimiter, "/",
|
||||
substr ($sub->name, strlen ($this->mailbox)));
|
||||
}
|
||||
$res = array_map (function ($folder) {
|
||||
return mb_convert_encoding ($folder, "UTF-8", "UTF7-IMAP");
|
||||
}, $res);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/** Add a subscription for a folder. The folder must be in UTF-8 */
|
||||
public function addSubscribe ($folder)
|
||||
{
|
||||
$folderUTF7 = mb_convert_encoding ($folder, "UTF7-IMAP","UTF-8");
|
||||
return imap_subscribe (self::$instance[$this->mailbox],
|
||||
$this->mailbox.$folder);
|
||||
}
|
||||
|
||||
/** Remove a subscription for a folder. The folder must be in UTF-8 */
|
||||
public function delSubscribe ($folder)
|
||||
{
|
||||
$folderUTF7 = mb_convert_encoding ($folder, "UTF7-IMAP","UTF-8");
|
||||
return imap_unsubscribe (self::$instance[$this->mailbox],
|
||||
$this->mailbox.$folder);
|
||||
}
|
||||
|
||||
/** Return the informations concerning a folder. It return an object with the
|
||||
following properties :
|
||||
Date date of last change (current datetime)
|
||||
Driver driver
|
||||
Mailbox name of the mailbox
|
||||
Nmsgs number of messages
|
||||
Recent number of recent messages
|
||||
Unread number of unread messages
|
||||
Deleted number of deleted messages
|
||||
Size mailbox size */
|
||||
public function getFolderInfo ($folder)
|
||||
{
|
||||
$oldFolder = $this->curDir;
|
||||
$this->changeFolder ($folder);
|
||||
$rc = imap_mailboxmsginfo (self::$instance[$this->mailbox]);
|
||||
$this->changeFolder ($oldFolder);
|
||||
if ($rc === false)
|
||||
throw new Exception ("Can't read information for folder $folder", 500);
|
||||
return $rc;
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
/// LIST MAILS ///
|
||||
//////////////////////
|
||||
/** Return an array of mailHeaders order by $field and by order ASC or DESC */
|
||||
public function imapSortMail ($mailHeaders, $field, $orderAsc = TRUE)
|
||||
{
|
||||
$this->changeFolder ($this->curDir);
|
||||
$sortList = array ();
|
||||
$sortInc = array ();
|
||||
foreach ($mailHeaders as $mail)
|
||||
{
|
||||
// Permit to have to mails with the same comparator field. Add an
|
||||
// increment at the end of field
|
||||
if (!isset ($sortInc[$mail->$field]))
|
||||
$inc = 1;
|
||||
else
|
||||
$inc = $sortInc[$mail->$field] + 1;
|
||||
$sortInc[$mail->$field] = $inc;
|
||||
$sortList[$mail->$field.$inc] = $mail;
|
||||
}
|
||||
ksort ($sortList, SORT_NATURAL);
|
||||
return array_values ($sortList);
|
||||
}
|
||||
|
||||
/** Fetch the headers for all messages in the current folder sorted by date
|
||||
Return an array of mail object containing information like the subject,
|
||||
the date, if the message is already read (recent), answered...
|
||||
(see http://www.php.net/manual/en/function.imap-fetch-overview.php)
|
||||
If the $from is negative, take the LAST $from mails
|
||||
If from is zero, it's value is override to 1
|
||||
For information, takes 0.4s to select 30 mails on 1552 **/
|
||||
public function mailsDate ($from = 1, $nbmails = 30)
|
||||
{
|
||||
$this->changeFolder ($this->curDir);
|
||||
if ($from === null)
|
||||
$from = 1;
|
||||
$MC = imap_check (self::$instance[$this->mailbox]);
|
||||
if ($MC->Nmsgs === 0)
|
||||
return array ();
|
||||
if ($nbmails > $MC->Nmsgs)
|
||||
$nbmails = $MC->Nmsgs;
|
||||
if ($from < 0)
|
||||
{
|
||||
$from = abs ($from);
|
||||
if ($from < 1)
|
||||
$from = 1;
|
||||
if ($from > $MC->Nmsgs)
|
||||
throw new Exception ("Mail start is higher than the number of mails",
|
||||
500);
|
||||
$from = $MC->Nmsgs - $from + 1;
|
||||
$to = $from + $nbmails - 1;
|
||||
if ($to > $MC->Nmsgs)
|
||||
$to = $MC->Nmsgs;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($from > $MC->Nmsgs)
|
||||
throw new Exception ("Mail start is higher than the number of mails",
|
||||
500);
|
||||
if ($from < 1)
|
||||
$from = 1;
|
||||
$to = $from + $nbmails - 1;
|
||||
if ($to > $MC->Nmsgs)
|
||||
$to = $MC->Nmsgs;
|
||||
}
|
||||
$headers = array ();
|
||||
// Adding the FT_UID options cost 1.1s
|
||||
$result = imap_fetch_overview (self::$instance[$this->mailbox],
|
||||
"$from:$to", 0);
|
||||
// imap_errors() takes the errors and clear the error stack
|
||||
$errors = imap_errors();
|
||||
return $result;
|
||||
}
|
||||
|
||||
/** Return all the mails numbers order by thread in an array.
|
||||
[] => array ("msgno"=>msgno, "depth"=>depth) */
|
||||
public function mailsThread ()
|
||||
{
|
||||
$this->changeFolder ($this->curDir);
|
||||
$threads = @imap_thread (self::$instance[$this->mailbox]);
|
||||
// imap_errors() takes the errors and clear the error stack
|
||||
$errors = imap_errors();
|
||||
$thread = array ();
|
||||
$depth = 0;
|
||||
foreach ($threads as $key => $val)
|
||||
{
|
||||
$tree = explode('.', $key);
|
||||
if ($tree[1] == 'num')
|
||||
{
|
||||
// If the mail unknown (the mails starts at 1), skip the thread record
|
||||
if ($val === 0)
|
||||
continue;
|
||||
$thread[] = array ("msgno"=>$val, "depth"=>$depth);
|
||||
$depth++;
|
||||
}
|
||||
elseif ($tree[1] == 'branch' && $depth > 0)
|
||||
{
|
||||
$depth--;
|
||||
}
|
||||
}
|
||||
return $thread;
|
||||
}
|
||||
|
||||
/** Send back the number of mails in the mailbox */
|
||||
public function mailsNumber ()
|
||||
{
|
||||
$this->changeFolder ($this->curDir);
|
||||
$MC = imap_check (self::$instance[$this->mailbox]);
|
||||
return $MC->Nmsgs;
|
||||
}
|
||||
|
||||
/** Return an array containing the msgno corresponding to the criteria */
|
||||
public function mailsSearch ($criteria)
|
||||
{
|
||||
$this->changeFolder ($this->curDir);
|
||||
return imap_search (self::$instance[$this->mailbox], $criteria);
|
||||
}
|
||||
|
||||
/** Move the mail provided in the $folder in UTF-8.
|
||||
If $msgno is an array, all the mails with the contain msgno are deleted
|
||||
Expunge automatically the current folder to remove the old emails */
|
||||
public function mailMove ($msgno, $folder)
|
||||
{
|
||||
$this->changeFolder ($this->curDir);
|
||||
if (is_array ($msgno))
|
||||
$msgno = implode (",", $msgno);
|
||||
$folderUTF7 = mb_convert_encoding ($folder, "UTF7-IMAP","UTF-8");
|
||||
$rc = imap_mail_move (self::$instance[$this->mailbox], $msgno, $folderUTF7);
|
||||
if ($rc !== TRUE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if ($this->autoexpunge)
|
||||
return imap_expunge (self::$instance[$this->mailbox]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Copy the mail provided in the $folder in UTF-8.
|
||||
If $msgno is an array, all the mails with the contain msgno are copied */
|
||||
public function mailCopy ($msgno, $folder)
|
||||
{
|
||||
$this->changeFolder ($this->curDir);
|
||||
if (is_array ($msgno))
|
||||
$msgno = implode (",", $msgno);
|
||||
$folderUTF7 = mb_convert_encoding ($folder, "UTF7-IMAP","UTF-8");
|
||||
$rc = imap_mail_copy (self::$instance[$this->mailbox], $msgno, $folderUTF7);
|
||||
if ($rc !== TRUE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Expunge the mailbox. If the autoexpunge is activated, it is normally not
|
||||
needed */
|
||||
public function expunge ()
|
||||
{
|
||||
$this->changeFolder ($this->curDir);
|
||||
return imap_expunge (self::$instance[$this->mailbox]);
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
/// GET/SET/DEL EMAIL ///
|
||||
/////////////////////////////
|
||||
/** Get an existing email in the current folder in raw format */
|
||||
public function getEmailRaw ($msgno)
|
||||
{
|
||||
$this->changeFolder ($this->curDir);
|
||||
// Clear the errors
|
||||
imap_errors();
|
||||
$content = @imap_fetchheader (self::$instance[$this->mailbox], $msgno)."\n".
|
||||
@imap_body (self::$instance[$this->mailbox], $msgno);
|
||||
$errors = imap_errors ();
|
||||
if ($errors !== false)
|
||||
throw new Exception ("Mail not found", 404);
|
||||
return $content;
|
||||
}
|
||||
|
||||
/** Get the headers of the email (in raw format) */
|
||||
public function getEmailHeadersRaw ($msgno)
|
||||
{
|
||||
$this->changeFolder ($this->curDir);
|
||||
// Clear the errors
|
||||
imap_errors();
|
||||
$content = @imap_fetchheader (self::$instance[$this->mailbox], $msgno);
|
||||
$errors = imap_errors ();
|
||||
if ($errors !== false)
|
||||
throw new Exception ("Mail not found", 404);
|
||||
return $content;
|
||||
}
|
||||
|
||||
/** Get all the body (and attached files) of an email in raw format */
|
||||
public function getEmailBodyRaw ($msgno)
|
||||
{
|
||||
$this->changeFolder ($this->curDir);
|
||||
// Clear the errors
|
||||
imap_errors();
|
||||
$content = @imap_body (self::$instance[$this->mailbox], $msgno);
|
||||
$errors = imap_errors ();
|
||||
if ($errors !== false)
|
||||
throw new Exception ("Mail not found", 404);
|
||||
return $content;
|
||||
}
|
||||
|
||||
/** Return email structure of the body */
|
||||
public function getStructure ($msgno)
|
||||
{
|
||||
$this->changeFolder ($this->curDir);
|
||||
// Clear the errors
|
||||
imap_errors();
|
||||
$structure = @imap_fetchstructure (self::$instance[$this->mailbox], $msgno);
|
||||
$errors = imap_errors ();
|
||||
if ($errors !== false)
|
||||
throw new Exception ("Mail not found", 404);
|
||||
return $structure;
|
||||
}
|
||||
|
||||
/** Return the structure of the mail body with the associated content */
|
||||
public function getStructureWithContent ($msgno)
|
||||
{
|
||||
$this->changeFolder ($this->curDir);
|
||||
// Clear the errors
|
||||
imap_errors();
|
||||
$structure = @imap_fetchstructure (self::$instance[$this->mailbox], $msgno);
|
||||
$errors = imap_errors ();
|
||||
if ($errors !== false)
|
||||
throw new Exception ("Mail not found", 404);
|
||||
if (! isset ($structure->parts))
|
||||
{
|
||||
// In case of PLAIN text, there is no parts
|
||||
$content = imap_fetchbody (self::$instance[$this->mailbox], $msgno, 1);
|
||||
if ($structure->encoding === 4)
|
||||
$content = quoted_printable_decode ($content);
|
||||
elseif ($structure->encoding === 3)
|
||||
$content = base64_decode ($content);
|
||||
foreach ($structure->parameters as $param)
|
||||
{
|
||||
if ($param->attribute === "charset")
|
||||
$content = iconv ($param->value, "utf-8", $content);
|
||||
}
|
||||
$structure->content = $content;
|
||||
return $structure;
|
||||
}
|
||||
foreach ($structure->parts as $part1=>$struct1)
|
||||
{
|
||||
if (isset ($struct1->parts))
|
||||
{
|
||||
foreach ($struct1->parts as $part2=>$struct2)
|
||||
{
|
||||
$content = imap_fetchbody (self::$instance[$this->mailbox], $msgno,
|
||||
($part1+1).".".($part2+1));
|
||||
if ($struct2->encoding === 4)
|
||||
$content = quoted_printable_decode ($content);
|
||||
elseif ($struct2->encoding === 3)
|
||||
$content = base64_decode ($content);
|
||||
foreach ($struct2->parameters as $param)
|
||||
{
|
||||
if ($param->attribute === "charset")
|
||||
$content = iconv ($param->value, "utf-8", $content);
|
||||
}
|
||||
$structure->parts[$part1]->parts[$part2]->content = $content;
|
||||
// Add the MIME type
|
||||
if ($struct2->type === 0)
|
||||
$structure->parts[$part1]->parts[$part2]->mimetype = "text/".
|
||||
strtolower ($struct2->subtype);
|
||||
elseif ($struct2->type === 1)
|
||||
$structure->parts[$part1]->parts[$part2]->mimetype = "multipart/".
|
||||
strtolower ($struct2->subtype);
|
||||
elseif ($struct2->type === 2)
|
||||
$structure->parts[$part1]->parts[$part2]->mimetype = "message/".
|
||||
strtolower ($struct2->subtype);
|
||||
elseif ($struct2->type === 3)
|
||||
$structure->parts[$part1]->parts[$part2]->mimetype = "application/".
|
||||
strtolower ($struct2->subtype);
|
||||
elseif ($struct2->type === 4)
|
||||
$structure->parts[$part1]->parts[$part2]->mimetype = "audio/".
|
||||
strtolower ($struct2->subtype);
|
||||
elseif ($struct2->type === 5)
|
||||
$structure->parts[$part1]->parts[$part2]->mimetype = "image/".
|
||||
strtolower ($struct2->subtype);
|
||||
elseif ($struct2->type === 6)
|
||||
$structure->parts[$part1]->parts[$part2]->mimetype = "video/".
|
||||
strtolower ($struct2->subtype);
|
||||
elseif ($struct2->type === 7)
|
||||
$structure->parts[$part1]->parts[$part2]->mimetype = "other/".
|
||||
strtolower ($struct2->subtype);
|
||||
else
|
||||
throw new Exception (sprintf (
|
||||
_("Unknown type in imap_fetchstructure : %s"),
|
||||
$struct2->type), 500);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$content = imap_fetchbody (self::$instance[$this->mailbox], $msgno,
|
||||
$part1+1);
|
||||
if ($struct1->encoding === 4)
|
||||
$content = quoted_printable_decode ($content);
|
||||
elseif ($struct1->encoding === 3)
|
||||
$content = base64_decode ($content);
|
||||
foreach ($struct1->parameters as $param)
|
||||
{
|
||||
if ($param->attribute === "charset")
|
||||
$content = iconv ($param->value, "utf-8", $content);
|
||||
}
|
||||
$structure->parts[$part1]->content = $content;
|
||||
// Add the MIME type
|
||||
if ($struct1->type === 0)
|
||||
$structure->parts[$part1]->mimetype = "text/".
|
||||
strtolower ($struct1->subtype);
|
||||
elseif ($struct1->type === 1)
|
||||
$structure->parts[$part1]->mimetype = "multipart/".
|
||||
strtolower ($struct1->subtype);
|
||||
elseif ($struct1->type === 2)
|
||||
$structure->parts[$part1]->mimetype = "message/".
|
||||
strtolower ($struct1->subtype);
|
||||
elseif ($struct1->type === 3)
|
||||
$structure->parts[$part1]->mimetype = "application/".
|
||||
strtolower ($struct1->subtype);
|
||||
elseif ($struct1->type === 4)
|
||||
$structure->parts[$part1]->mimetype = "audio/".
|
||||
strtolower ($struct1->subtype);
|
||||
elseif ($struct1->type === 5)
|
||||
$structure->parts[$part1]->mimetype = "image/".
|
||||
strtolower ($struct1->subtype);
|
||||
elseif ($struct1->type === 6)
|
||||
$structure->parts[$part1]->mimetype = "video/".
|
||||
strtolower ($struct1->subtype);
|
||||
elseif ($struct1->type === 7)
|
||||
$structure->parts[$part1]->mimetype = "other/".
|
||||
strtolower ($struct1->subtype);
|
||||
else
|
||||
throw new Exception (sprintf (
|
||||
_("Unknown type in imap_fetchstructure : %s"),
|
||||
$struct1->type), 500);
|
||||
}
|
||||
}
|
||||
return $structure;
|
||||
}
|
||||
|
||||
/** Return the content of a part of the mail body defined in the structure in
|
||||
an object, with the associated mimetype, the parameters like the charset
|
||||
if they are defined, the number of lines associated to this part in the
|
||||
mail and some other info */
|
||||
public function getStructureContent ($msgno, $part)
|
||||
{
|
||||
$structure = $this->getStructureWithContent ($msgno);
|
||||
if (isset ($structure->parts[$part]))
|
||||
return $structure->parts[$part];
|
||||
throw new Exception ("Part not found in the mail", 404);
|
||||
}
|
||||
|
||||
/** Return the part identifiers of the structure of the mail body. To be used
|
||||
in getStructureContent */
|
||||
public function getStructureParts ($msgno)
|
||||
{
|
||||
$structure = $this->getStructure ($msgno);
|
||||
if (! isset ($structure->parts))
|
||||
return array ();
|
||||
return array_keys ($structure->parts);
|
||||
}
|
||||
|
||||
/** Delete all the mailIDs (msgno) provided in an array or a single mail if
|
||||
$msgno is not an array
|
||||
DO NOT MOVE THE MAIL IN TRASH, DESTROY THE MAIL REALLY
|
||||
Expunge the mails at the end of the operation */
|
||||
public function mailsDel ($msgno)
|
||||
{
|
||||
$this->changeFolder ($this->curDir);
|
||||
if (is_array ($msgno))
|
||||
$msgno = implode (",", $msgno);
|
||||
$rc = @imap_delete (self::$instance[$this->mailbox], $msgno);
|
||||
imap_errors();
|
||||
if ($rc === FALSE)
|
||||
throw new Exception ("No mailID provided can be found : ABORT");
|
||||
if ($this->autoexpunge)
|
||||
return imap_expunge(self::$instance[$this->mailbox]);
|
||||
return $rc;
|
||||
}
|
||||
|
||||
/** Add a new mail in the current folder. The content must be a string
|
||||
containing all the mail (header and body). If the content is invalid, the
|
||||
directory listing can provide erroneous data */
|
||||
public function mailAdd ($content)
|
||||
{
|
||||
$folderUTF7 = mb_convert_encoding ($this->curDir, "UTF7-IMAP","UTF-8");
|
||||
$rc = imap_append (self::$instance[$this->mailbox],
|
||||
$this->mailbox.$folderUTF7,
|
||||
$content);
|
||||
$errors = imap_errors();
|
||||
if ($rc === FALSE)
|
||||
throw new Exception ("Error when saving the mail in folder : ".
|
||||
implode (" ", $errors), 500);
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////
|
||||
/// QUOTA ///
|
||||
/////////////////
|
||||
/** Return the quota used by the user in Mo */
|
||||
public function getQuota ()
|
||||
{
|
||||
$quota = @imap_get_quotaroot (self::$instance[$this->mailbox], "INBOX");
|
||||
imap_errors();
|
||||
if (! isset ($quota["STORAGE"]))
|
||||
return array ();
|
||||
|
||||
return array_map (function ($n) {return intval ($n/1000);},
|
||||
$quota["STORAGE"]);
|
||||
}
|
||||
|
||||
/////////////////
|
||||
/// FLAGS ///
|
||||
/////////////////
|
||||
/** Set the flags of the msgno. If msgno is an array, the flags will be write
|
||||
on the list of mails. The others flags of the email are not modified.
|
||||
The flags must be an array containing :
|
||||
\Seen Message has been read
|
||||
\Answered Message has been answered
|
||||
\Flagged Message is "flagged" for urgent/special attention
|
||||
\Deleted Message is "deleted" for removal by later EXPUNGE
|
||||
\Draft Message has not completed composition (marked as a draft). */
|
||||
public function setFlag ($msgno, $flags)
|
||||
{
|
||||
$this->changeFolder ($this->curDir);
|
||||
if (is_array ($msgno))
|
||||
$msgno = implode (",", $msgno);
|
||||
$rc = @imap_setflag_full (self::$instance[$this->mailbox], $msgno,
|
||||
implode (" ", $flags));
|
||||
imap_errors();
|
||||
if ($rc === FALSE)
|
||||
throw new Exception ("Can't define the flags", 500);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Unset the flags of the msgno. If msgno is an array, the flags will be
|
||||
write on the list of mails. The others flags of the email are not
|
||||
modified.
|
||||
The flags must be an array containing :
|
||||
\Seen Message has been read
|
||||
\Answered Message has been answered
|
||||
\Flagged Message is "flagged" for urgent/special attention
|
||||
\Deleted Message is "deleted" for removal by later EXPUNGE
|
||||
\Draft Message has not completed composition (marked as a draft). */
|
||||
public function unsetFlag ($msgno, $flags)
|
||||
{
|
||||
$this->changeFolder ($this->curDir);
|
||||
if (is_array ($msgno))
|
||||
$msgno = implode (",", $msgno);
|
||||
$rc = @imap_clearflag_full (self::$instance[$this->mailbox], $msgno,
|
||||
implode (" ", $flags));
|
||||
imap_errors();
|
||||
if ($rc === FALSE)
|
||||
throw new Exception ("Can't define the flags", 500);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Mark mail(s) as read.
|
||||
If msgno is an array, a list of mails will be modified.
|
||||
If msgno is an integer, only one mail will be modified */
|
||||
public function markMailAsRead ($msgno)
|
||||
{
|
||||
$this->changeFolder ($this->curDir);
|
||||
if (is_array ($msgno))
|
||||
$msgno = implode (",", $msgno);
|
||||
$rc = @imap_setflag_full (self::$instance[$this->mailbox], $msgno,
|
||||
"\\Seen");
|
||||
imap_errors();
|
||||
if ($rc === FALSE)
|
||||
throw new Exception ("Can't mark mail as read", 500);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Mark mail(s) as unread.
|
||||
If msgno is an array, a list of mails will be modified.
|
||||
If msgno is an integer, only one mail will be modified */
|
||||
public function markMailAsUnread ($msgno)
|
||||
{
|
||||
$this->changeFolder ($this->curDir);
|
||||
if (is_array ($msgno))
|
||||
$msgno = implode (",", $msgno);
|
||||
$rc = @imap_clearflag_full (self::$instance[$this->mailbox], $msgno,
|
||||
"\\Seen");
|
||||
imap_errors();
|
||||
if ($rc === FALSE)
|
||||
throw new Exception ("Can't mark mail as read", 500);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user