Files
DomFramework/src/Imap.php
2022-11-25 21:21:30 +01:00

989 lines
36 KiB
PHP

<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/** IMAP connection abstraction
In the IMAP terminology, "mailbox" is a folder in the mailbox of the user */
class Imap
{
/** The mailbox string */
private $mailbox = null;
/** 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 SSL tunnelled is 993
* @param string|null $imapserver The IMAP server to connect. Localhost is
* used if not defined
* @param integer|null $imapport The IMAP port to connect. 143 is used if not
* defined
* @param string|null $username The username to connect
* @param string|null $password The password to connect
* @param boolean|null $imapssl Use the SSL connection layer. Not used by
* default
* @param boolean|null $imapcertvalidate Check the certificates if using the
* SSL connection. True by default
*/
public function __construct(
$imapserver = "localhost",
$imapport = 143,
$username = null,
$password = null,
$imapssl = false,
$imapcertvalidate = true
) {
$this->connect(
$imapserver,
$imapport,
$username,
$password,
$imapssl,
$imapcertvalidate
);
}
/** The connect can be used when extends the imap class. The constructor can
* be override by the child class.
* The IMAP standard port is 143, but SSL tunnelled is 993
* @param string|null $imapserver The IMAP server to connect. Localhost is
* used if not defined
* @param integer|null $imapport The IMAP port to connect. 143 is used if not
* defined
* @param string|null $username The username to connect
* @param string|null $password The password to connect
* @param boolean|null $imapssl Use the SSL connection layer. Not used by
* default
* @param boolean|null $imapcertvalidate Check the certificates if using the
* SSL connection. True by default
*/
public function connect(
$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();
if (
substr($e->getMessage(), 0, 35) ===
"Can not authenticate to IMAP server"
) {
throw new \Exception("IMAP error : " . $e->getMessage(), 401);
}
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()
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$list = array_keys($this->foldersListWithAttr());
sort($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()
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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
* @param string $folder Change to the provided folder
*/
public function changeFolder($folder)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
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()
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
return $this->curDir;
}
/** Create a new folder, provided in UTF-8. The folder must be absolute
* @param string $folder Create the provided folder
*/
public function createFolder($folder)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
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
* @param string $folder The folder to delete
*/
public function deleteFolder($folder)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
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()
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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);
sort($res);
return $res;
}
/** Add a subscription for a folder. The folder must be in UTF-8
* @param string $folder Add the provided folder to the subscription file of
* the user
*/
public function addSubscribe($folder)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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
* @param string $folder Remove the provided folder to the subscription file
* of the user
*/
public function delSubscribe($folder)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$folderUTF7 = mb_convert_encoding($folder, "UTF7-IMAP", "UTF-8");
return imap_unsubscribe(
self::$instance[$this->mailbox],
$this->mailbox . $folder
);
}
/** Return the information 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
* @param string $folder The folder to get the informations
*/
public function getFolderInfo($folder)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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
* @param array $mailHeaders The headers to sort
* @param string $field The field to examine
* @param boolean|null $orderAsc The order of sorting. Asc if not defined
*/
public function imapSortMail($mailHeaders, $field, $orderAsc = true)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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
* @param integer|null $from The selector of the mails. 1 if not defined
* @param integer|null $nbmails The number of mails returned by the method
* 30 if not defined
**/
public function mailsDate($from = 1, $nbmails = 30)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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()
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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()
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$this->changeFolder($this->curDir);
$MC = imap_check(self::$instance[$this->mailbox]);
return $MC->Nmsgs;
}
/** Return an array containing the msgno corresponding to the criteria
* @param string $criteria The criteria to use for the IMAP search
*/
public function mailsSearch($criteria)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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
* @param integer|array $msgno The message number(s) to copy
* @param string $folder The destination folder of the move. Must exists
*/
public function mailMove($msgno, $folder)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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
* @param integer|array $msgno The message number(s) to copy
* @param string $folder The destination folder of the copy. Must exists
*/
public function mailCopy($msgno, $folder)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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()
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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
* @param integer $msgno The message number to examine
*/
public function getEmailRaw($msgno)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$this->changeFolder($this->curDir);
// Clear the errors
imap_errors();
$content = @imap_fetchheader(self::$instance[$this->mailbox], $msgno) .
"\r\n" .
@imap_body(self::$instance[$this->mailbox], $msgno);
$errors = imap_errors();
if ($errors !== false || $content === "\n") {
throw new \Exception("Mail not found", 404);
}
return $content;
}
/** Get the headers of the email (in raw format)
* @param integer $msgno The message number to examine
*/
public function getEmailHeadersRaw($msgno)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$this->changeFolder($this->curDir);
// Clear the errors
imap_errors();
$content = @imap_fetchheader(self::$instance[$this->mailbox], $msgno);
$errors = imap_errors();
if ($errors !== false || $content === "") {
throw new \Exception("Mail not found", 404);
}
return $content;
}
/** Get all the body (and attached files) of an email in raw format
* @param integer $msgno The message number to examine
*/
public function getEmailBodyRaw($msgno)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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
* @param integer $msgno The message number to examine
*/
public function getStructure($msgno)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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
* @param integer $msgno The message number to examine
*/
public function getStructureWithContent($msgno)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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(
dgettext(
"domframework",
"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(
dgettext(
"domframework",
"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
* @param integer $msgno The message number to examine
* @param integer $part The message part to get
*/
public function getStructureContent($msgno, $part)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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
* @param integer $msgno The message number to examine
*/
public function getStructureParts($msgno)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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
* @param array|integer $msgno The message number(s) to remove
*/
public function mailsDel($msgno)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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
* @param string $content the content of the mail to add
*/
public function mailAdd($content)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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()
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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).
* @param integer|array $msgno The messages number(s) to add the flags
* @param array $flags The flags to add
*/
public function setFlag($msgno, $flags)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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).
* @param integer|array $msgno The messages number(s) to remove the flags
* @param array $flags The flags to remove
*/
public function unsetFlag($msgno, $flags)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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
* @param integer|array $msgno The messages number(s) to mark as read
*/
public function markMailAsRead($msgno)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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
* @param integer|array $msgno The messages number(s) to mark as unread
*/
public function markMailAsUnread($msgno)
{
if ($this->mailbox === null) {
throw new \Exception("IMAP server not connected", 500);
}
$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;
}
}