imap class / mail controller

add imap class to access captured emails
add mail controller to framework (display content)
This commit is contained in:
Markus Warg 2010-04-14 15:20:40 +02:00
parent d09a673644
commit ae053ad037
10 changed files with 867 additions and 1 deletions

View file

@ -0,0 +1,24 @@
<?php
/**
* @author markus
* $Id: IndexController.php 6 2009-11-18 14:52:50Z markus $
*/
require_once(LIBRARY_PATH . '/imap/imapConnection.php');
class MailController extends Zend_Controller_Action
{
public function init()
{
/* Initialize action controller here */
}
public function indexAction()
{
// action body
}
}

View file

@ -0,0 +1,7 @@
<?php
/**
* @author markus
* $Id: index.phtml 25 2009-12-02 15:43:21Z markus $
*/
?>
<H1><?php print I18n::_('Mail'); ?></H1>

View file

@ -0,0 +1,53 @@
<?php
require_once (FWACTIONS_PATH . '/FWAction.php');
class Login extends FWAction {
/**
* get a list of required permissions that are needed to access this action
* @return array
*/
public static function getRequiredPermissions() {
return array();
}
/**
* get a role that is required for accessing that action
* @return string
*/
public static function getRequiredRole() {
return 'User';
}
/**
* sort order for top navigation
* @return integer
*/
public static function getTopNavPrio() {
return 1000;
}
/**
* controller to invoke
* @return string
*/
public static function getController() {
return 'login';
}
/**
* action to invoke
* @return string
*/
public static function getAction() {
return 'index';
}
/**
* get text for menu, caller is responsible for translating
* @return string
*/
public static function getMenuText() {
return 'Login';
}
}

View file

@ -0,0 +1,53 @@
<?php
require_once (FWACTIONS_PATH . '/FWAction.php');
class Mail extends FWAction {
/**
* get a list of required permissions that are needed to access this action
* @return array
*/
public static function getRequiredPermissions() {
return array();
}
/**
* get a role that is required for accessing that action
* @return string
*/
public static function getRequiredRole() {
return 'User';
}
/**
* sort order for top navigation
* @return integer
*/
public static function getTopNavPrio() {
return 100;
}
/**
* controller to invoke
* @return string
*/
public static function getController() {
return 'mail';
}
/**
* action to invoke
* @return string
*/
public static function getAction() {
return 'index';
}
/**
* get text for menu, caller is responsible for translating
* @return string
*/
public static function getMenuText() {
return 'Mail';
}
}

View file

@ -0,0 +1,34 @@
<?php
/**
* @author markus
* $Id: $
*/
/**
* required files
* @ignore
*/
require_once(LIBRARY_PATH . '/exception/exception.Base.php');
/**
* Exceptions thrown in the IMAP classes
*
* @package SLS
* @subpackage CONFIG.EXCEPTION
* @author Markus Warg <mw@it-sls.de>
*/
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);
}
*/
}

View file

@ -0,0 +1,559 @@
<?php
/**
* @author markus
* $Id: $
*/
/**
* required files
* @ignore
*/
require_once('exception.IMAPException.php');
define('IMAP_RETRIES', 5);
/**
* Wraps PHP built in imap commands within a class, features open, hold, close connection and
* issue imap commands.
*
* @author markus
*/
class imapConnection {
/**
* Array mit den bereits vorhandenen Instanzen
* @var array
*/
private static $instances = array();
/**
* Instanzname, die unterschiedlichen Entitäten werden über den Namen
* auseinandergehalten.
* @var string
*/
private $instanceName = '';
/**
* Configsection
* @var Config
*/
private $config = null;
/**
* IMAP Resource
* @var imap_stream
*/
private $imap = null;
/**
* Servername, Port, Flags
* @var string
*/
private $server = '';
/**
* Name der zuletzt geöffneten Mailbox
* @var string
*/
private $mbox = '';
/**
* wird auf true gesetzt, wenn imapPing die Connection neu aufbaut
* @var boolean
*/
private $reopenedConnection = false;
/**
* liefert eine Liste der verfügbaren Folder
* @param string $pattern
* @return array
*/
public function imapList($pattern = '*') {
if ($this->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;
}
}

View file

@ -0,0 +1,16 @@
<?php
/**
* @author markus
* $Id: $
*/
/**
* required files
* @ignore
*/
/**
* eine Mail, die per imapConnection vom Server geholt wurde
*
* ToDo
*/

View file

@ -0,0 +1,18 @@
<?php
/**
* @author markus
* $Id: $
*/
/**
* required files
* @ignore
*/
require_once(LIBRARY_PATH . '/imap/class.imapMail.php');
/**
* Container, um imapMail Objekte zu gruppieren
*/
class imapMailContainer {
}

View file

@ -0,0 +1,96 @@
<?php
/**
* @author markus
* $Id: $
*/
/**
* required files
* @ignore
*/
require_once('exception.IMAPException.php');
/**
* Supportklasse für imapCleanMailbox
* Soll den in der Config pro Mailbox angegebenen Action-String auswerten
* und in eine automatisiert weiterverarbeitbare Form bringen.
*/
class imapParseAction {
/**
* Actions als Konstanten
* @var integer
*/
const IMAP_ACTION_DELETE = 1;
const IMAP_ACTION_ARCHIVE = 2;
/**
* gesetzte Action
* @var integer
*/
private $action = 0;
/**
* Modifikator keep gesetzt?
* @var boolean
*/
private $delete_keep = false;
/**
* Wert des Modifikators keep
* @var integer
*/
private $delete_keep_num = 0;
/**
* getAction
* @return integer
*/
public function getAction() {
return $this->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;
}
}
}
}

View file

@ -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('<a href="' .
$view->url(array('controller' => $controller), 'default', true) .
'">' . I18n::_($text) . '</a>', Zend_View_Helper_Placeholder_Container_Abstract::SET, 1000);
'"' . $aclass . '>' . I18n::_($text) . '</a>', Zend_View_Helper_Placeholder_Container_Abstract::SET, 1000);
}
}