config = acym_config();
$this->mailer = acym_get('helper.mailer');
$this->bounceClass = acym_get('class.bounce');
$this->ruleClass = acym_get('class.rule');
$this->mailer->report = false;
$this->mailer->alreadyCheckedAddresses = true;
$this->userClass = acym_get('class.user');
$this->mailClass = acym_get('class.mail');
$this->historyClass = acym_get('class.history');
$this->encodingHelper = acym_get('helper.encoding');
$charset = acym_get('type.charset');
$this->allCharsets = $charset->charsets;
$this->allowed_extensions = explode(',', $this->config->get('allowed_files', ''));
$this->detectEmail = '/'.acym_getEmailRegex(false, true).'/i';
}
public function init()
{
$this->server = $this->config->get('bounce_server');
$this->username = $this->config->get('bounce_username');
$this->password = $this->config->get('bounce_password');
$this->port = $this->config->get('bounce_port', '');
$this->connectMethod = $this->config->get('bounce_connection');
$this->secureMethod = $this->config->get('bounce_secured', '');
$this->selfSigned = $this->config->get('bounce_certif', false);
$this->timeout = $this->config->get('bounce_timeout');
if ($this->connectMethod == 'pear') {
$this->usepear = true;
include_once(ACYM_INC.'pear'.DS.'pop3.php');
return true;
}
if (extension_loaded("imap") || function_exists('imap_open')) {
return true;
}
$prefix = (PHP_SHLIB_SUFFIX == 'dll') ? 'php_' : '';
$EXTENSION = $prefix.'imap.'.PHP_SHLIB_SUFFIX;
if (function_exists('dl')) {
$fatalMessage = 'The system tried to load dynamically the '.$EXTENSION.' extension';
$fatalMessage .= '
If you see this message, that means the system could not load this PHP extension';
$fatalMessage .= '
Please enable the PHP Extension '.$EXTENSION;
ob_start();
echo $fatalMessage;
dl($EXTENSION);
$warnings = str_replace($fatalMessage, '', ob_get_clean());
if (extension_loaded("imap") || function_exists('imap_open')) {
return true;
}
}
if ($this->report) {
acym_display('The extension "'.$EXTENSION.'" could not be loaded, please change your PHP configuration to enable it or use the pop3 method without imap extension', 'error');
if (!empty($warnings)) {
acym_display($warnings, 'warning');
}
}
return false;
}
public function connect()
{
if ($this->usepear) {
return $this->_connectpear();
}
return $this->_connectimap();
}
private function _connectpear()
{
ob_start();
$this->mailbox = new Net_POP3();
$timeout = $this->timeout;
if (!empty($timeout)) {
$this->mailbox->setTimeOut($timeout);
}
$port = intval($this->port);
$secure = $this->secureMethod;
if (empty($port)) {
if ($secure == 'ssl') {
$port = '995';
} else {
$port = '110/pop3/notls';
}
}
$serverName = trim($this->server);
if (!empty($secure) && !strpos($serverName, '://')) {
$serverName = $secure.'://'.$serverName;
}
if (!$this->mailbox->connect($serverName, $port)) {
$warnings = ob_get_clean();
if ($this->report) {
acym_enqueueMessage(acym_translation_sprintf("ACYM_ERROR_CONNECTING", $this->server." : ".$port), 'error');
}
if (!empty($warnings) && $this->report) {
acym_display($warnings, 'warning');
}
return false;
}
$login = $this->mailbox->login(trim($this->username), trim($this->password), 'USER');
if (empty($login) || isset($login->code)) {
$warnings = ob_get_clean();
if ($this->report) {
acym_enqueueMessage(acym_translation_sprintf('ACYM_ERROR_LOGIN', $this->username.':'.$this->password), 'error');
}
if (!empty($warnings) && $this->report) {
acym_display($warnings, 'warning');
}
return false;
}
ob_end_clean();
return true;
}
private function _connectimap()
{
if (empty($this->server)) {
acym_enqueueMessage(acym_translation('ACYM_CONFIGURE_BOUNCE'), 'warning');
return false;
}
ob_start();
$buff = imap_alerts();
$buff = imap_errors();
$timeout = intval($this->timeout);
if (!empty($timeout)) {
imap_timeout(IMAP_OPENTIMEOUT, $timeout);
}
$port = intval($this->port);
$secure = $this->secureMethod;
$protocol = $this->connectMethod;
$serverName = '{'.trim($this->server);
if (empty($port)) {
if ($secure == 'ssl' && $protocol == 'imap') {
$port = '993';
} elseif ($secure == 'ssl' && $protocol == 'pop3') {
$port = '995';
} elseif ($protocol == 'imap') {
$port = '143';
} elseif ($protocol == 'pop3') {
$port = '110';
}
}
if (!empty($port)) {
$serverName .= ':'.$port;
}
if (!empty($secure)) {
$serverName .= '/'.$secure;
}
if ($this->selfSigned) {
$serverName .= '/novalidate-cert';
}
if (!empty($protocol)) {
$serverName .= '/service='.$protocol;
}
$serverName .= '}';
$this->mailbox = imap_open($serverName, trim($this->username), trim($this->password), OP_SILENT);
$warnings = ob_get_clean();
if ($this->report) {
if (!$this->mailbox) {
acym_enqueueMessage(acym_translation_sprintf('ACYM_ERROR_CONNECTING', $serverName), 'error');
}
if (!empty($warnings)) {
acym_enqueueMessage($warnings, 'warning');
}
}
return $this->mailbox ? true : false;
}
public function getNBMessages()
{
if ($this->usepear) {
$this->nbMessages = $this->mailbox->numMsg();
} else {
$this->nbMessages = imap_num_msg($this->mailbox);
}
return $this->nbMessages;
}
public function getMessage($msgNB)
{
if ($this->usepear) {
$message = new stdClass();
$message->headerString = $this->mailbox->getRawHeaders($msgNB);
if (empty($message->headerString)) {
return false;
}
} else {
$message = imap_headerinfo($this->mailbox, $msgNB);
}
return $message;
}
public function deleteMessage($msgNB)
{
if ($this->usepear) {
$this->mailbox->deleteMsg($msgNB);
} else {
imap_delete($this->mailbox, $msgNB);
imap_expunge($this->mailbox);
}
}
public function close()
{
if ($this->usepear) {
$this->mailbox->disconnect();
} else {
imap_close($this->mailbox);
}
}
private function decodeMessage()
{
if ($this->usepear) {
return $this->_decodeMessagepear();
} else {
return $this->_decodeMessageimap();
}
}
private function _decodeMessagepear()
{
$this->_message->headerinfo = $this->mailbox->getParsedHeaders($this->_message->messageNB);
if (empty($this->_message->headerinfo['subject'])) {
return false;
}
$this->_message->text = '';
$this->_message->html = $this->mailbox->getBody($this->_message->messageNB);
if (!empty($this->_message->headerinfo['content-type']) && strpos($this->_message->headerinfo['content-type'], 'boundary') !== false) {
$matches = [];
preg_match('#boundary="([^"]+)"#i', $this->_message->headerinfo['content-type'], $matches);
if (!empty($matches[1]) && strpos($this->_message->html, $matches[1]) !== false) {
$inlineImages = [];
$segments = explode('--'.$matches[1], $this->_message->html);
foreach ($segments as $segment) {
if (strpos($segment, "Content-Type: text/plain") !== false) {
$matches = [];
preg_match('#boundary="([^"]+)"#i', $segment, $matches);
if (!empty($matches[1])) {
$parts = explode('--'.$matches[1], $segment);
foreach ($parts as $onePart) {
$content = trim(preg_replace('#(charset=".*?\r\n)|Content-(Type|ID|Disposition|Transfer-Encoding):.*?\r\n#is', "", $onePart));
if (strpos($onePart, 'Content-Transfer-Encoding') !== false) {
preg_match('#Content-Transfer-Encoding: (.+)#i', $onePart, $encoding);
$encoding = trim($encoding[1]);
$content = mb_convert_encoding($content, 'UTF-8', $encoding);
}
if (strpos($onePart, "Content-Type: text/plain") !== false) {
$this->_message->text = $content;
}
if (strpos($onePart, "Content-Type: text/html") !== false) {
$this->_message->html = $content;
}
}
} else {
$this->_message->html = trim(preg_replace('#(charset=".*?\r\n)|Content-(Type|ID|Disposition|Transfer-Encoding):.*?\r\n#is', "", $segment));
}
} elseif (preg_match("#Content-Type: .*?/(png|jpg|jpeg|gif)#i", $segment) !== false) {
preg_match('#name="([^"]+)"#i', $segment, $filename);
if (empty($filename) || empty($filename[1])) {
continue;
}
$name = trim($filename[1]);
$filename = $name;
$extensionPos = strrpos($filename, '.');
if ($extensionPos === false) {
continue;
}
$extension = substr($filename, $extensionPos + 1);
$filename = preg_replace('#[^a-zA-Z0-9]#Uis', '_', substr($filename, 0, $extensionPos));
$uploadFolder = str_replace(['/', '\\'], DS, acym_getFilesFolder());
$pathToUpload = ACYM_ROOT.trim($uploadFolder, DS).DS;
if (file_exists($pathToUpload.$filename.'.'.$extension)) {
$fileNumber = 1;
while (file_exists($pathToUpload.$filename.'_('.$fileNumber.').'.$extension)) {
$fileNumber++;
}
$filename = $filename.'_('.$fileNumber.')';
}
preg_match('#Content-ID: <([^>]+)>#i', $segment, $contentID);
if (empty($contentID) || empty($contentID[1])) {
continue;
}
$contentID = trim($contentID[1]);
$data = trim(substr($segment, strpos($segment, "\r\n\r\n")));
if (strpos($segment, 'Content-Transfer-Encoding: base64') !== false) {
$data = base64_decode($data);
}
try {
if (acym_writeFile($pathToUpload.$filename.'.'.$extension, $data)) {
$inlineImages['cid:'.$contentID] = acym_rootURI().$uploadFolder.'/'.$filename.'.'.$extension;
}
} catch (Exception $e) {
$this->_display(acym_translation_sprintf('ACYM_ERROR_UPLOAD_ATTACHMENT', $filename.'.'.$extension, $e->getMessage()), false);
}
}
}
if (!empty($inlineImages)) {
$this->_message->html = str_replace(array_keys($inlineImages), $inlineImages, $this->_message->html);
}
}
}
$this->_message->subject = $this->_decodeHeader($this->_message->headerinfo['subject']);
if (empty($this->_message->header)) {
$this->_message->header = new stdClass();
}
$this->_message->header->sender_email = @$this->_message->headerinfo['return-path'];
if (is_array($this->_message->header->sender_email)) {
$this->_message->header->sender_email = reset($this->_message->header->sender_email);
}
if (preg_match($this->detectEmail, $this->_message->header->sender_email, $results)) {
$this->_message->header->sender_email = $results[0];
}
$this->_message->header->sender_name = strip_tags(@$this->_message->headerinfo['from']);
$this->_message->header->reply_to_email = $this->_message->header->sender_email;
$this->_message->header->reply_to_name = $this->_message->header->sender_name;
$this->_message->header->from_email = $this->_message->header->sender_email;
$this->_message->header->from_name = $this->_message->header->sender_name;
return true;
}
private function _decodeMessageimap()
{
$this->_message->structure = imap_fetchstructure($this->mailbox, $this->_message->messageNB);
if (empty($this->_message->structure)) {
return false;
}
$this->_message->headerinfo = imap_fetchheader($this->mailbox, $this->_message->messageNB);
$this->_message->html = '';
$this->_message->text = '';
if ($this->_message->structure->type == 1) {
$this->_message->contentType = 2;
if ($this->_message->structure->subtype == "MIXED") {
$allParts = $this->_explodeBodyMixed($this->_message->structure);
} else {
$allParts = $this->_explodeBody($this->_message->structure);
}
$text = '';
foreach ($allParts as $num => $onePart) {
$decodedContent = $this->_decodeContent(imap_fetchbody($this->mailbox, $this->_message->messageNB, $num), $onePart);
if ($onePart->subtype == 'HTML') {
$this->_message->html .= $decodedContent;
} else {
if ($onePart->subtype == 'PLAIN') {
$text .= $decodedContent."\n";
}
$this->_message->text .= $decodedContent."\n\n- - -\n\n";
}
}
if (!empty($this->action) && empty($this->_message->html)) {
$this->_message->html = $text."\n";
}
if (!empty($this->inlineImages)) {
$this->_message->html = str_replace(array_keys($this->inlineImages), $this->inlineImages, $this->_message->html);
}
} else {
if ($this->_message->structure->subtype == 'HTML') {
$this->_message->contentType = 1;
$this->_message->html = $this->_decodeContent(imap_body($this->mailbox, $this->_message->messageNB), $this->_message->structure);
} else {
$this->_message->contentType = 0;
$this->_message->text = $this->_decodeContent(imap_body($this->mailbox, $this->_message->messageNB), $this->_message->structure);
}
}
$this->_message->subject = $this->_decodeHeader($this->_message->subject);
$this->_decodeAddressimap('sender');
$this->_decodeAddressimap('from');
$this->_decodeAddressimap('reply_to');
$this->_decodeAddressimap('to');
return true;
}
public function handleMessages()
{
$maxMessages = min($this->nbMessages, $this->config->get('bounce_max', 0));
if (empty($maxMessages)) {
$maxMessages = min($this->nbMessages, 500);
}
if ($this->report) {
if (function_exists('apache_get_modules')) {
$modules = apache_get_modules();
$this->mod_security2 = in_array('mod_security2', $modules);
}
@ini_set('output_buffering', 'off');
@ini_set('zlib.output_compression', 0);
if (!headers_sent()) {
while (ob_get_level() > 0 && $this->obend++ < 3) {
@ob_end_flush();
}
}
$disp = "