summaryrefslogtreecommitdiff
path: root/manager/library/imap
diff options
context:
space:
mode:
authorMarkus Warg <mw@it-sls.de>2010-04-14 15:20:40 +0200
committerMarkus Warg <mw@it-sls.de>2010-04-14 15:20:40 +0200
commitae053ad0371d46f529a26c2a18953189620b88e4 (patch)
treeaad5ebb03e7138647f950be8960c3f7c84df0020 /manager/library/imap
parentd09a673644f87ee067f62f3de978cb046a02c7a8 (diff)
downloadcacert-mgr-ae053ad0371d46f529a26c2a18953189620b88e4.tar.gz
cacert-mgr-ae053ad0371d46f529a26c2a18953189620b88e4.tar.xz
cacert-mgr-ae053ad0371d46f529a26c2a18953189620b88e4.zip
imap class / mail controller
add imap class to access captured emails add mail controller to framework (display content)
Diffstat (limited to 'manager/library/imap')
-rw-r--r--manager/library/imap/exception.IMAPException.php34
-rw-r--r--manager/library/imap/imapConnection.php559
-rw-r--r--manager/library/imap/imapMail.php16
-rw-r--r--manager/library/imap/imapMailContainer.php18
-rw-r--r--manager/library/imap/imapParseAction.php96
5 files changed, 723 insertions, 0 deletions
diff --git a/manager/library/imap/exception.IMAPException.php b/manager/library/imap/exception.IMAPException.php
new file mode 100644
index 0000000..4672f6a
--- /dev/null
+++ b/manager/library/imap/exception.IMAPException.php
@@ -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);
+ }
+ */
+}
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 @@
+<?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;
+ }
+
+
+}
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 @@
+<?php
+/**
+ * @author markus
+ * $Id: $
+ */
+
+/**
+ * required files
+ * @ignore
+ */
+
+/**
+ * eine Mail, die per imapConnection vom Server geholt wurde
+ *
+ * ToDo
+ */
diff --git a/manager/library/imap/imapMailContainer.php b/manager/library/imap/imapMailContainer.php
new file mode 100644
index 0000000..e4bd280
--- /dev/null
+++ b/manager/library/imap/imapMailContainer.php
@@ -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 {
+
+}
diff --git a/manager/library/imap/imapParseAction.php b/manager/library/imap/imapParseAction.php
new file mode 100644
index 0000000..d9e3fb0
--- /dev/null
+++ b/manager/library/imap/imapParseAction.php
@@ -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;
+ }
+ }
+ }
+}