function send_outbox_mails() { session_commit(); set_time_limit(0); $utils = new MailUtilities(); if (!array_var($_GET, 'acc_id')) { $userAccounts = MailAccounts::getMailAccountsByUser(logged_user()); } else { $account = MailAccounts::findById(array_var($_GET, 'acc_id')); $userAccounts = array($account); } $old_memory_limit = ini_get('memory_limit'); if (php_config_value_to_bytes($old_memory_limit) < 256 * 1024 * 1024) { ini_set('memory_limit', '256M'); } foreach ($userAccounts as $account) { $accountUser = null; if (logged_user() instanceof User) { $accountUser = MailAccountUsers::getByAccountAndUser($account, logged_user()); } if (!$account || !$accountUser) { flash_error(lang('no access permissions')); ajx_current("empty"); return; } $errorMailId = 0; try { $mails = MailContents::findAll(array("conditions" => array("`is_deleted`=0 AND `state` >= 200 AND `account_id` = ? AND `created_by_id` = ?", $account->getId(), $accountUser->getUserId()), "order" => "`state` ASC")); $count = 0; foreach ($mails as $mail) { // Only send mails with pair status if ($mail->getState() % 2 == 1) { continue; } // Set impair status, to avoid sending it again when sending it in parallel if (!$mail->addToStatus(1)) { continue; } try { $errorMailId = $mail->getId(); $to = $mail->getTo(); $from = array($account->getEmailAddress() => $account->getFromName()); $subject = $mail->getSubject(); $body = $mail->getBodyHtml() != '' ? $mail->getBodyHtml() : $mail->getBodyPlain(); $cc = $mail->getCc(); $bcc = $mail->getBcc(); $type = $mail->getBodyHtml() != '' ? 'text/html' : 'text/plain'; $msg_id = $mail->getMessageId(); $in_reply_to_id = $mail->getInReplyToId(); $attachments = self::readAttachmentsFromFileSystem($mail, $att_version); if ($mail->getBodyHtml() != '') { $images = get_image_paths($body); } else { $images = null; } $mail->setSentDate(DateTimeValueLib::now()); $mail->setReceivedDate(DateTimeValueLib::now()); if (defined('DEBUG') && DEBUG) { file_put_contents(ROOT . "/cache/log_mails.txt", gmdate("d-m-Y H:i:s") . " antes de enviar: " . $mail->getId() . "\n", FILE_APPEND); } $sentOK = $utils->sendMail($account->getSmtpServer(), $to, $from, $subject, $body, $cc, $bcc, $attachments, $account->getSmtpPort(), $account->smtpUsername(), $account->smtpPassword(), $type, $account->getOutgoingTrasnportType(), $msg_id, $in_reply_to_id, $images, $complete_mail, $att_version); } catch (Exception $e) { // actions are taken below depending on the sentOK variable Logger::log("Could not send email: " . $e->getMessage() . "\nmail_id=" . $mail->getId()); $sentOK = false; } try { if ($sentOK) { DB::beginWork(); $mail->setState(3); $mail->save(); DB::commit(); } else { Logger::log("Swift returned sentOK = false after sending email\nmail_id=" . $mail->getId()); // set status to a higher and pair value, to retry later. if (!$mail->addToStatus(1)) { Logger::log("Swift could not send the email and the state could not be set to retry later.\nmail_id=" . $mail->getId()); } } } catch (Exception $e) { Logger::log("Exception marking email as sent: " . $e->getMessage() . "\nmail_id=" . $mail->getId()); if ($sentOK) { DB::rollback(); } } if (defined('DEBUG') && DEBUG) { file_put_contents(ROOT . "/cache/log_mails.txt", gmdate("d-m-Y H:i:s") . " despues de enviar: " . $mail->getId() . "\n", FILE_APPEND); } try { //if user selected the option to keep a copy of sent mails on the server if ($sentOK && config_option("sent_mails_sync") && $account->getSyncServer() != null && $account->getSyncSsl() != null && $account->getSyncSslPort() != null && $account->getSyncFolder() != null && $account->getSyncAddr() != null && $account->getSyncPass() != null) { $check_sync_box = MailUtilities::checkSyncMailbox($account->getSyncServer(), $account->getSyncSsl(), $account->getOutgoingTrasnportType(), $account->getSyncSslPort(), $account->getSyncFolder(), $account->getSyncAddr(), $account->getSyncPass()); if ($check_sync_box) { MailUtilities::sendToServerThroughIMAP($account->getSyncServer(), $account->getSyncSsl(), $account->getOutgoingTrasnportType(), $account->getSyncSslPort(), $account->getSyncFolder(), $account->getSyncAddr(), $account->getSyncPass(), $complete_mail); } } } catch (Exception $e) { Logger::log("Could not save sent mail in server through imap: " . $e->getMessage() . "\nmail_id=" . $mail->getId()); } if (defined('DEBUG') && DEBUG) { file_put_contents(ROOT . "/cache/log_mails.txt", gmdate("d-m-Y H:i:s") . " antes de try: " . $mail->getId() . "\n", FILE_APPEND); } try { if ($sentOK) { if (defined('DEBUG') && DEBUG) { file_put_contents(ROOT . "/cache/log_mails.txt", gmdate("d-m-Y H:i:s") . " sentOK=true: " . $mail->getId() . "\n", FILE_APPEND); } if (FileRepository::isInRepository($mail->getContentFileId())) { if ($att_version >= 2) { // delete attachments from repository foreach ($attachments as $att) { if (FileRepository::isInRepository($att['repo_id'])) { FileRepository::deleteFile($att['repo_id']); } } if (is_file($att['path'])) { @unlink($att['path']); } // if file was copied to tmp -> delete it if (defined('DEBUG') && DEBUG) { file_put_contents(ROOT . "/cache/log_mails.txt", gmdate("d-m-Y H:i:s") . " deleted attachments: " . $mail->getId() . "\n", FILE_APPEND); } } FileRepository::deleteFile($mail->getContentFileId()); if (defined('DEBUG') && DEBUG) { file_put_contents(ROOT . "/cache/log_mails.txt", gmdate("d-m-Y H:i:s") . " deleted att list: " . $mail->getId() . "\n", FILE_APPEND); } } } } catch (Exception $e) { Logger::log("Exception deleting tmp repository files (attachment list): " . $e->getMessage() . "\nmail_id=" . $mail->getId()); } try { DB::beginWork(); if ($sentOK) { $content = $complete_mail; $repository_id = $utils->saveContent($content); if (defined('DEBUG') && DEBUG) { file_put_contents(ROOT . "/cache/log_mails.txt", gmdate("d-m-Y H:i:s") . " content saved: " . $mail->getId() . "\n", FILE_APPEND); } $mail->setContentFileId($repository_id); $mail->setSize(strlen($content)); if (config_option("sent_mails_sync") && isset($check_sync_box) && $check_sync_box) { $mail->setSync(true); } $mail->save(); if (defined('DEBUG') && DEBUG) { file_put_contents(ROOT . "/cache/log_mails.txt", gmdate("d-m-Y H:i:s") . " email saved: " . $mail->getId() . "\n", FILE_APPEND); } $properties = array("id" => $mail->getId()); evt_add("mail sent", $properties); $count++; } DB::commit(); } catch (Exception $e) { DB::rollback(); Logger::log("Exception deleting tmp repository files (attachment list): " . $e->getMessage() . "\nmail_id=" . $mail->getId()); } } if ($count > 0) { evt_add("mails sent", $count); } } catch (Exception $e) { $errorEmailUrl = ''; if ($errorMailId > 0) { $email = MailContents::findById($errorMailId); if ($email instanceof MailContent) { Logger::log("failed to send mail: " . $e->getMessage() . "\n" . $email->getEditUrl()); Logger::log($e->getTraceAsString()); $errorEmailUrl = $email->getEditUrl(); } } flash_error($errorEmailUrl != '' ? $e->getMessage() : $e->getMessage()); ajx_current("empty"); } } ini_set('memory_limit', $old_memory_limit); ajx_current("empty"); }
/** * Delete uploaded theme image if not tied into anything. * * @param URLPATH The URL to the theme image being deleted */ function cleanup_theme_images($old_url) { $files_referenced = collapse_1d_complexity('path', $GLOBALS['SITE_DB']->query_select('theme_images', array('DISTINCT path'))); $themes = find_all_themes(); foreach (array_keys($themes) as $theme) { $files_existing = get_image_paths(get_custom_base_url() . '/themes/' . rawurlencode($theme) . '/images_custom/', get_custom_file_base() . '/themes/' . $theme . '/images_custom/'); foreach (array_keys($files_existing) as $path) { $path = str_replace(get_custom_file_base() . '/', '', filter_naughty($path)); $encoded_path = substr($path, 0, strrpos($path, '/') + 1) . rawurlencode(substr($path, strrpos($path, '/') + 1)); if (!in_array($path, $files_referenced) && !in_array($encoded_path, $files_referenced) && ($old_url == $path || $old_url == $encoded_path)) { @unlink(get_custom_file_base() . '/' . $path); sync_file($path); } } } }
/** * Search under a base path for image FILE URLs (not actually paths as function name would suggest). * * @param URLPATH The base-URL to where we are searching for images * @param PATH The base-path to where we are searching for images * @return array path->url map of found images */ function get_image_paths($base_url, $base_path) { $out = array(); require_code('images'); $handle = @opendir($base_path); if ($handle !== false) { while (false !== ($file = readdir($handle))) { if (!should_ignore_file($file, IGNORE_ACCESS_CONTROLLERS)) { $this_path = $base_path . $file; if (is_file($this_path)) { if (is_image($file)) { $this_url = $base_url . rawurlencode($file); $out[$this_path] = $this_url; } } elseif (strlen($file) != 2 || strtoupper($file) != $file) { $out = array_merge($out, get_image_paths($base_url . $file . '/', $base_path . $file . '/')); } } } closedir($handle); } return $out; }
function send_outbox_mails($user = null, $user_account = null, $from_time = null) { if (is_null($user)) { $user = logged_user(); } $from_time_cond = ""; if (!is_null($from_time) && $from_time instanceof DateTimeValue) { $from_time_cond = " AND `created_on` > '" . $from_time->toMySQL() . "'"; } session_commit(); set_time_limit(0); $utils = new MailUtilities(); if (!is_null($user_account)) { $userAccounts = array($user_account); } elseif (array_var($_GET, 'acc_id')) { $account = MailAccounts::findById(array_var($_GET, 'acc_id')); $userAccounts = array($account); } else { $userAccounts = MailAccounts::getMailAccountsByUser($user); } $old_memory_limit = ini_get('memory_limit'); if (php_config_value_to_bytes($old_memory_limit) < 256 * 1024 * 1024) { ini_set('memory_limit', '256M'); } foreach ($userAccounts as $account) { $accountUser = null; if ($user instanceof Contact) { $accountUser = MailAccountContacts::getByAccountAndContact($account, $user); } if (!$account || !$accountUser) { flash_error(lang('no access permissions')); ajx_current("empty"); return; } $errorMailId = 0; try { $mails = MailContents::findAll(array("conditions" => array("`is_deleted`=0 AND `state` >= 200 AND `account_id` = ? AND `created_by_id` = ? {$from_time_cond}", $account->getId(), $accountUser->getContactId()), "order" => "`state` ASC")); $count = 0; foreach ($mails as $mail) { /* @var $mail MailContent */ if ($mail->getTrashedById() > 0) { continue; } // Only send mails with pair status if ($mail->getState() % 2 == 1) { continue; } //if is archived do not send it if ($mail->isArchived()) { continue; } // Set impair status, to avoid sending it again when sending it in parallel if (!$mail->addToStatus(1)) { continue; } try { $errorMailId = $mail->getId(); $to = $mail->getTo(); if (!$accountUser instanceof MailAccountContact) { $from = array($account->getEmailAddress() => $account->getFromName()); } else { if ($user instanceof Contact && $accountUser->getIsDefault() && $accountUser->getSenderName() == "") { $from = array($account->getEmailAddress() => $user->getObjectName()); } else { $from = array($account->getEmailAddress() => $accountUser->getSenderName()); } } $subject = $mail->getSubject(); $body = $mail->getBodyHtml() != '' ? $mail->getBodyHtml() : $mail->getBodyPlain(); $cc = $mail->getCc(); $bcc = $mail->getBcc(); $type = $mail->getBodyHtml() != '' ? 'text/html' : 'text/plain'; $msg_id = $mail->getMessageId(); $in_reply_to_id = $mail->getInReplyToId(); $attachments = self::readAttachmentsFromFileSystem($mail, $att_version); if ($mail->getBodyHtml() != '') { $images = get_image_paths($body); } else { $images = null; } // Inline images preg_match_all("/<img[^>]*src=[\"'][^\"']*[\"']/", $body, $matches); foreach ($matches as $match) { $pos = strpos($match[0], 'src="'); $url = substr($match[0], $pos + 5); $url = substr($url, 0, -1); if (str_starts_with($url, ROOT_URL . "/tmp/")) { $path = str_replace(ROOT_URL, ROOT, $url); if (!is_array($images)) { $images = array(); } $images[$url] = $path; } if (str_starts_with($url, "data:")) { $mime_type = substr($url, 5, strpos($url, ';') - 5); $extension = substr($mime_type, strpos($mime_type, "/") + 1); if (!is_array($images)) { $images = array(); } $file_url = ROOT_URL . "/tmp/" . gen_id() . ".{$extension}"; $path = str_replace(ROOT_URL, ROOT, $file_url); $data = substr($url, strpos($url, "base64") + 6); file_put_contents($path, base64_decode($data)); $images[$file_url] = $path; $body = str_replace($url, $file_url, $body); } } $mail->setSentDate(DateTimeValueLib::now()); $mail->setReceivedDate(DateTimeValueLib::now()); if (defined('DEBUG') && DEBUG) { file_put_contents(ROOT . "/cache/log_mails.txt", gmdate("d-m-Y H:i:s") . " antes de enviar: " . $mail->getId() . "\n", FILE_APPEND); } $sentOK = $utils->sendMail($account->getSmtpServer(), $to, $from, $subject, $body, $cc, $bcc, $attachments, $account->getSmtpPort(), $account->smtpUsername(), $account->smtpPassword(), $type, $account->getOutgoingTrasnportType(), $msg_id, $in_reply_to_id, $images, $complete_mail, $att_version); $mail->orderConversation(); } catch (Exception $e) { // actions are taken below depending on the sentOK variable Logger::log("Could not send email: " . $e->getMessage() . "\nmail_id=" . $mail->getId()); $sentOK = false; } try { if ($sentOK) { DB::beginWork(); $mail->setState(3); $mail->save(); DB::commit(); } else { Logger::log("Swift returned sentOK = false after sending email\nmail_id=" . $mail->getId()); // set status to a higher and pair value, to retry later. if (!$mail->addToStatus(1)) { Logger::log("Swift could not send the email and the state could not be set to retry later.\nmail_id=" . $mail->getId()); } } } catch (Exception $e) { $extra_exception_info = $sentOK == true ? '(but it has been sent)' : '(and it has NOT been sent)'; Logger::log("Exception marking email as sent " . $extra_exception_info . ": " . $e->getMessage() . "\nmail_id=" . $mail->getId()); if ($sentOK) { DB::rollback(); } } if (defined('DEBUG') && DEBUG) { file_put_contents(ROOT . "/cache/log_mails.txt", gmdate("d-m-Y H:i:s") . " despues de enviar: " . $mail->getId() . "\n", FILE_APPEND); } try { //if user selected the option to keep a copy of sent mails on the server if ($sentOK && config_option("sent_mails_sync") && $account->getSyncServer() != null && $account->getSyncSsl() != null && $account->getSyncSslPort() != null && $account->getSyncFolder() != null && $account->getSyncAddr() != null && $account->getSyncPass() != null) { $check_sync_box = MailUtilities::checkSyncMailbox($account->getSyncServer(), $account->getSyncSsl(), $account->getOutgoingTrasnportType(), $account->getSyncSslPort(), $account->getSyncFolder(), $account->getSyncAddr(), $account->getSyncPass()); if ($check_sync_box) { MailUtilities::sendToServerThroughIMAP($account->getSyncServer(), $account->getSyncSsl(), $account->getOutgoingTrasnportType(), $account->getSyncSslPort(), $account->getSyncFolder(), $account->getSyncAddr(), $account->getSyncPass(), $complete_mail); } } } catch (Exception $e) { Logger::log("Could not save sent mail in server through imap: " . $e->getMessage() . "\nmail_id=" . $mail->getId()); } if (defined('DEBUG') && DEBUG) { file_put_contents(ROOT . "/cache/log_mails.txt", gmdate("d-m-Y H:i:s") . " antes de try: " . $mail->getId() . "\n", FILE_APPEND); } try { if ($sentOK) { if (defined('DEBUG') && DEBUG) { file_put_contents(ROOT . "/cache/log_mails.txt", gmdate("d-m-Y H:i:s") . " sentOK=true: " . $mail->getId() . "\n", FILE_APPEND); } if (FileRepository::isInRepository($mail->getContentFileId())) { if ($att_version >= 2) { // delete attachments from repository foreach ($attachments as $att) { if (FileRepository::isInRepository($att['repo_id'])) { FileRepository::deleteFile($att['repo_id']); } } if (isset($att['path']) && is_file($att['path'])) { @unlink($att['path']); } // if file was copied to tmp -> delete it if (defined('DEBUG') && DEBUG) { file_put_contents(ROOT . "/cache/log_mails.txt", gmdate("d-m-Y H:i:s") . " deleted attachments: " . $mail->getId() . "\n", FILE_APPEND); } } FileRepository::deleteFile($mail->getContentFileId()); if (defined('DEBUG') && DEBUG) { file_put_contents(ROOT . "/cache/log_mails.txt", gmdate("d-m-Y H:i:s") . " deleted att list: " . $mail->getId() . "\n", FILE_APPEND); } } } else { if (defined('DEBUG') && DEBUG) { file_put_contents(ROOT . "/cache/log_mails.txt", gmdate("d-m-Y H:i:s") . " sentOK=false: " . $mail->getId() . " - Error when sending mail: SentOK = false \n", FILE_APPEND); } } } catch (Exception $e) { Logger::log("Exception deleting tmp repository files (attachment list): " . $e->getMessage() . "\nmail_id=" . $mail->getId()); } try { DB::beginWork(); if ($sentOK) { $content = $complete_mail; $repository_id = $utils->saveContent($content); if (defined('DEBUG') && DEBUG) { file_put_contents(ROOT . "/cache/log_mails.txt", gmdate("d-m-Y H:i:s") . " content saved: " . $mail->getId() . "\n", FILE_APPEND); } $mail->setContentFileId($repository_id); $mail->setSize(strlen($content)); if (config_option("sent_mails_sync") && isset($check_sync_box) && $check_sync_box) { $mail->setSync(true); } $mail->save(); if (defined('DEBUG') && DEBUG) { file_put_contents(ROOT . "/cache/log_mails.txt", gmdate("d-m-Y H:i:s") . " email saved: " . $mail->getId() . "\n", FILE_APPEND); } $properties = array("id" => $mail->getId()); evt_add("mail sent", $properties); $count++; } DB::commit(); } catch (Exception $e) { DB::rollback(); Logger::log("Exception deleting tmp repository files (attachment list): " . $e->getMessage() . "\nmail_id=" . $mail->getId()); } } if ($count > 0) { evt_add("mails sent", $count); } } catch (Exception $e) { $errorEmailUrl = ''; if ($errorMailId > 0) { $email = MailContents::findById($errorMailId); if ($email instanceof MailContent) { Logger::log("failed to send mail: " . $e->getMessage() . "\n" . $email->getEditUrl()); Logger::log($e->getTraceAsString()); $errorEmailUrl = $email->getEditUrl(); } } flash_error($errorEmailUrl != '' ? $e->getMessage() : $e->getMessage()); ajx_current("empty"); } } ini_set('memory_limit', $old_memory_limit); ajx_current("empty"); }