From ae053ad0371d46f529a26c2a18953189620b88e4 Mon Sep 17 00:00:00 2001 From: Markus Warg Date: Wed, 14 Apr 2010 15:20:40 +0200 Subject: [PATCH] imap class / mail controller add imap class to access captured emails add mail controller to framework (display content) --- .../controllers/MailController.php | 24 + .../views/scripts/mail/index.phtml | 7 + manager/library/actions/ActionLogin.php | 53 ++ manager/library/actions/ActionMail.php | 53 ++ .../library/imap/exception.IMAPException.php | 34 ++ manager/library/imap/imapConnection.php | 559 ++++++++++++++++++ manager/library/imap/imapMail.php | 16 + manager/library/imap/imapMailContainer.php | 18 + manager/library/imap/imapParseAction.php | 96 +++ .../library/plugins/plugin.loginlogout.php | 8 +- 10 files changed, 867 insertions(+), 1 deletion(-) create mode 100644 manager/application/controllers/MailController.php create mode 100644 manager/application/views/scripts/mail/index.phtml create mode 100644 manager/library/actions/ActionLogin.php create mode 100644 manager/library/actions/ActionMail.php create mode 100644 manager/library/imap/exception.IMAPException.php create mode 100644 manager/library/imap/imapConnection.php create mode 100644 manager/library/imap/imapMail.php create mode 100644 manager/library/imap/imapMailContainer.php create mode 100644 manager/library/imap/imapParseAction.php diff --git a/manager/application/controllers/MailController.php b/manager/application/controllers/MailController.php new file mode 100644 index 0000000..afe902b --- /dev/null +++ b/manager/application/controllers/MailController.php @@ -0,0 +1,24 @@ + +

diff --git a/manager/library/actions/ActionLogin.php b/manager/library/actions/ActionLogin.php new file mode 100644 index 0000000..02bae86 --- /dev/null +++ b/manager/library/actions/ActionLogin.php @@ -0,0 +1,53 @@ + + */ +class IMAPException extends BaseException { + /** + * make new object + * + * @access public + * @param string $message + * @param int $code + * @param string $extra + */ + /* + public function __construct($message,$code = 0,$extra = '') { + parent::__construct($message,$code, $extra); + } + */ +} diff --git a/manager/library/imap/imapConnection.php b/manager/library/imap/imapConnection.php new file mode 100644 index 0000000..f78dc3d --- /dev/null +++ b/manager/library/imap/imapConnection.php @@ -0,0 +1,559 @@ +imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + $this->imapPing(true); + + return imap_list($this->imap, $this->server, $pattern); + } + + + /** + * Checkt die Anzahl Messages in einer Mailbox + * return array + */ + public function imapCheck() { + if ($this->imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + $this->imapPing(true); + + return imap_check($this->imap); + } + + + /** + * per imap_reopen die aktuelle Connection auf eine andere mbox umstellen + * @param string $mbox + * @return boolean + */ + public function imapSwitchMbox($mbox) { + if ($this->imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + $this->imapPing(true); + + if (imap_reopen($this->imap, $this->server.$mbox) === false) { + throw new IMAPException(__METHOD__ . ' reopen failed'); + } + + $this->mbox = $mbox; + + return true; + } + + + /** + * setzt ein Flag bei allen in $sequence aufgeführten Messages + * @param string $sequence + * @param string $flag + * @param integer $options + * @return boolean + */ + public function imapSetflagFull($sequence, $flag, $options = 0) { + if ($this->imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + $this->imapPing(true); + + return imap_setflag_full($this->imap, $sequence, $flag, $options); + } + + + /** + * liefert die Mailheader + * @return array + */ + public function imapHeaders() { + if ($this->imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + $this->imapPing(true); + + return imap_headers($this->imap); + } + + /** + * liefert die Header zu genau einer Mail mit der gegebenen ID + * @param integer $number + * @return array + */ + public function imapHeader($number) { + if ($this->imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + $this->imapPing(true); + + return imap_headerinfo($this->imap, $number); + } + + /** + * liefert die Header zu genau einer Mail mit der gegebenen UID + * @param integer $uid + * @return array + */ + public function imapFetchHeader($uid) { + if ($this->imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + + $ret = imap_fetchheader($this->imap, $uid, FT_UID); + + return $ret; + } + + /** + * liefert die Header zu genau einer Mail mit der gegebenen UID + * @param integer $uid + * @return array + */ + public function imapFetchOverview($uid) { + if ($this->imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + + $ret = imap_fetch_overview($this->imap, $uid, FT_UID); + + return $ret[0]; + } + + /** + * liefert den Body zu genau einer Mail mit der gegebenen ID + * @param integer $number + * @return string + */ + public function imapBody($number) { + if ($this->imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + $this->imapPing(true); + + return imap_body($this->imap, $number); + } + + /** + * liefert den Body zu genau einer Mail mit der gegebenen UID + * @param integer $uid + * @return string + */ + public function imapBodyByUID($uid) { + if ($this->imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + $this->imapPing(true); + + return imap_body($this->imap, $uid, FT_UID ); + } + + /** + * markiert die Nachricht mit der unique ID zum löschen + * @param integer $uid + * return boolean + */ + public function imapDelete($uid) { + if ($this->imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + $this->imapPing(true); + + $ret = imap_delete($this->imap, $uid, FT_UID); + + if ($ret !== true) { + print "imap delete returned false for ".$uid."\n"; + } + + return $ret; + } + + /** + * löscht alle zum löschen markierten Nachrichten + * @return boolean + */ + public function imapExpunge() { + if ($this->imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + $this->imapPing(true); + + return imap_expunge($this->imap); + } + + /** + * kopiert die Nachricht mit der gegebenen uid in die gegebene Mailbox *auf dem selben Server* + * @param integer $uid + * @param string $dest_mbox + * @return boolean + */ + public function imapMailCopy($uid, $dest_mbox) { + if ($this->imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + $this->imapPing(true); + + return imap_mail_copy($this->imap, $uid, $dest_mbox, CP_UID); + } + + /** + * verschiebt die Nachricht mit der gegebenen uid in die gegebene Mailbox *auf dem selben Server* + * @param integer $uid + * @param string $dest_mbox + * @return boolean + */ + public function imapMailMove($uid, $dest_mbox) { + if ($this->imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + $this->imapPing(true); + /* + * dont't add the server part, + * only the mailbox name works fine + * + * $dest_mbox = $this->server.$dest_mbox; + */ + return imap_mail_move( $this->imap, $uid, $dest_mbox, CP_UID); + } + + /** + * legt eine neue Mailbox *auf dem selben Server* an + * @param string $mbox + * @return boolean + */ + public function imapCreateMailbox($mbox) { + if ($this->imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + $this->imapPing(true); + + return imap_createmailbox($this->imap, $this->server.$mbox); + } + + /** + * fragt ab, ob eine mbox unterhalb von mbox_root existiert und liefert true zurück, falls ja + * Funktion existiert nicht direkt als IMAP Kommando, aus einzelnen Kommando's zusammengebaut + * + * @param string $mbox_root + * @param string $mbox + * @return boolean + */ + public function imapMailboxExists($mbox_root, $mbox) { + if ($this->imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + $this->imapPing(true); + + $folderlist = $this->imapList($mbox_root); + $foundFolder = false; + foreach ($folderlist as $folder) { + if (strpos($folder, $mbox) !== false) { + return true; + } + } + + return false; + } + + const AR_YYYY = 'Y'; + const AR_YYYYMM = 'Ym'; + const AR_YYYYMMDD = 'Ymd'; + + /** + * erzeugt eine Archivmailbox zur Mailbox $mbox, dabei wird das Archiv unterhalb von $mbox + * auf dem selben Server angelegt, der Name der Mailbox enthält je nach $mode noch einen Datumsstamp + * Wenn der Input ($mbox) bereits mehrere Ebenen enthält (NOC3.domain.incoming z.B.), dann + * wird automatisch nur der am weitesten rechts stehende Teil extrahiert und benutzt. + * NOC3.domain.incoming => NOC3.domain.incoming.incoming-200705 + * @param string $mbox + * @param string $mode + * @param integer $timestamp + * @param string $delimiter + * @return string + */ + public static function imapMakeArchiveName($mbox, $mode, $timestamp = null, $delimiter = '-') { + if ($timestamp === null) + $timestamp = time(); + + $ar = explode('.', $mbox); + + $sub_mbox = $ar[count($ar) - 1]; + + return $mbox.'.'.$sub_mbox.$delimiter.date($mode,$timestamp); + } + + public static function imapMakePrefixedArchiveName($mbox, $mode, $prefix = '', $timestamp = null, $delimiter = '-') { + if ($timestamp === null) + $timestamp = time(); + + $ar = explode('.', $mbox); + + $sub_mbox = $ar[count($ar) - 1]; + + return $mbox.'.'.$prefix.$delimiter.$sub_mbox.$delimiter.date($mode,$timestamp); + } + + /** + * liefert die unique ID der Nachricht mit der laufenden msg_number + * @param integer $msg_number + * @return integer + */ + public function imapUID($msg_number) { + if ($this->imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + $this->imapPing(true); + + return imap_uid($this->imap, $msg_number); + } + + + /** + * liefert die laufende msg_number der Nachricht, die die unique ID uid hat + * @param integer $uid + * @return integer + */ + public function imapMsgNo($uid) { + if ($this->imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + $this->imapPing(true); + + return imap_msgno($this->imap, $uid); + } + + + /** + * prüft, ob die Connection noch aktiv ist, Exception falls keine Connection definiert ist, + * oder die Connection geschlossen wurde + * wenn reconnect = true, dann wird bei einer geschlossenen Connection die Connection neu aufgebaut + * @param boolean $reconnect + * @return boolean + */ + public function imapPing($reconnect = false) { + if ($this->imap === null) { + throw new IMAPException(__METHOD__ . ' not connected'); + } + + $ret = imap_ping($this->imap); + + if ($ret === false) { + if ($reconnect === true) { + $this->imap = $this->imapOpen($this->server.$this->mbox, + $this->config->getValue('username'), + $this->config->getValue('password'), + OP_HALFOPEN); + + $ret = imap_ping($this->imap); + + if ($ret === false) { + throw new IMAPException(__METHOD__ . ' reconnect failed'); + } + + $this->reopenedConnection = true; + } + else { + throw new IMAPException(__METHOD__ . ' not connected'); + } + } + + return true; + } + + + public function __destruct() { + if ($this->imap !== null) { + imap_close($this->imap); + $this->imap = null; + } + } + + + /** + * true, wenn imapPing die Connection neu aufgemacht hat + * Variable wird auf false gesetzt wenn $flush true ist + * @param boolean $flush + * @return boolean + */ + public function connectionReopened($flush = true) { + $ret = $this->reopenedConnection; + if ($flush === true) { + $this->reopenedConnection = false; + } + return $ret; + } + + + /** + * interne IMAP Open Methode + * + * @param string $servername + * @param string $username + * @param string password + * @param integer $flags + * @return resource + */ + protected function imapOpen($server, $username, $password, $flags) { + return imap_open($server, $username, $password, $flags); + } + + + /** + * privater Konstruktor, wird exklusiv von getInstance aufgerufen + * + * @param $instanceName + * @param $config + */ + protected function __construct($instanceName,$config) { + $this->instanceName = $instanceName; + $this->config = $config; + + if (!$this->config->hasValue('mailhost')) { + throw new IMAPException(__METHOD__ . ' config attribute missing: "mailhost"'); + } + if (!$this->config->hasValue('username')) { + throw new IMAPException(__METHOD__ . ' config attribute missing: "username"'); + } + if (!$this->config->hasValue('password')) { + throw new IMAPException(__METHOD__ . ' config attribute missing: "password"'); + } + if (!$this->config->hasValue('port')) { + throw new IMAPException(__METHOD__ . ' config attribute missing: "port"'); + } + + $this->server = '{'.$this->config->getValue('mailhost').':'.$this->config->getValue('port').'/imap'; + if( $this->config->hasValue('use_tls') && + $this->config->getValue('use_tls') == true ) { + $this->server .= '/tls'; + } + $this->server .= '/novalidate-cert}'; + + $mbox = ''; + + $this->mbox = $mbox; + + $this->imap = null; + + $this->imap = $this->imapOpen($this->server.$mbox, + $this->config->getValue('username'), + $this->config->getValue('password'), + OP_HALFOPEN); + + if ($this->imap === false) { + $this->imap = null; + throw new IMAPException(__METHOD__ . ' not connected'); + } + + $this->reopenedConnection = false; + } + + + /** + * sucht nach einer bereits vorhandenen Instanz, wird keine gefunden, + * dann wird eine neue Instanz angelegt. + * Man kann die Config-Variable weglassen, wenn man sicher ist, dass + * bereits eine Instanz mit dem gewünschten instanceName existiert, + * existiert aber keiner, dann liefert getInstance eine Exception. + * + * @param $instance + * @param $config + * @return imapConnection + */ + public static function getInstance($instanceName,$config = null) { + if (!self::$instances) + self::$instances = array(); + + foreach (self::$instances as $instance) { + if ($instance->getInstanceName() == $instanceName) + return $instance; + } + + if (!$config instanceof Config) { + throw new IMAPException(__METHOD__ . ' no config'); + } + + $object = new imapConnection($instanceName, $config); + + self::$instances[] = $object; + + return $object; + } + + + /** + * Liefert den Namen der aktuellen Instanz + * @return string + */ + public function getInstanceName() { + return $this->instanceName; + } + + +} diff --git a/manager/library/imap/imapMail.php b/manager/library/imap/imapMail.php new file mode 100644 index 0000000..e211cb4 --- /dev/null +++ b/manager/library/imap/imapMail.php @@ -0,0 +1,16 @@ +action; + } + + /** + * getDeleteKeep + * @return boolean + */ + public function getDeleteKeep() { + return $this->delete_keep; + } + + /** + * getDeleteKeepNum + * @return integer + */ + public function getDeleteKeepNum() { + return $this->delete_keep_num; + } + + /** + * Konstruktor, parst eine Zeile mit Tokens und ermittelt, welche Aktionen + * auf einer Mailbox ausgeführt werden sollen + * @param string $action + */ + public function __construct($action) { + $args = explode(' ', $action); + + $numargs = count($args); + + for ($arg = 0; $arg < $numargs; $arg++) { + switch ($args[$arg]) { + case 'delete': + $this->action = self::IMAP_ACTION_DELETE; + break; + case 'keep': + $arg++; + $this->delete_keep = true; + $this->delete_keep_num = $args[$arg]; + break; + default: + /** + * @todo Exception werfen + */ + break; + } + } + } +} diff --git a/manager/library/plugins/plugin.loginlogout.php b/manager/library/plugins/plugin.loginlogout.php index 6de7a92..8bd13db 100644 --- a/manager/library/plugins/plugin.loginlogout.php +++ b/manager/library/plugins/plugin.loginlogout.php @@ -17,9 +17,15 @@ class LoginLogout extends Zend_Controller_Plugin_Abstract { $controller = 'logout'; $text = 'Logout'; } + $cur_ctrl = $request->getControllerName(); + if ($cur_ctrl == 'login') + $aclass=' class="active"'; + else + $aclass=''; + $view = Zend_Registry::get('view'); $view->topNav('' . I18n::_($text) . '', Zend_View_Helper_Placeholder_Container_Abstract::SET, 1000); + '"' . $aclass . '>' . I18n::_($text) . '', Zend_View_Helper_Placeholder_Container_Abstract::SET, 1000); } }