Skip to content

Commit

Permalink
Merge pull request #288 from SSFGizmo/11.x
Browse files Browse the repository at this point in the history
compatibility to TYPO3 11.x LTS
  • Loading branch information
kartolo authored Sep 27, 2022
2 parents 102236a + b9e7cc0 commit 08b6c0a
Show file tree
Hide file tree
Showing 99 changed files with 12,165 additions and 6,363 deletions.
56 changes: 56 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# EditorConfig is awesome: http://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true

# TS/JS-Files
[*.{ts,js}]
indent_size = 2

# JSON-Files
[*.json]
indent_style = tab

# ReST-Files
[*.rst]
indent_size = 4
max_line_length = 80

# YAML-Files
[*.{yaml,yml}]
indent_size = 2

# NEON-Files
[*.neon]
indent_size = 2
indent_style = tab

# package.json
[package.json]
indent_size = 2

# TypoScript
[*.{typoscript,tsconfig}]
indent_size = 2

# XLF-Files
[*.xlf]
indent_style = tab

# SQL-Files
[*.sql]
indent_style = tab
indent_size = 2

# .htaccess
[{_.htaccess,.htaccess}]
indent_style = tab
274 changes: 274 additions & 0 deletions Classes/Command/AnalyzeBounceMailCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
<?php
namespace DirectMailTeam\DirectMail\Command;

use DirectMailTeam\DirectMail\Dmailer;
use DirectMailTeam\DirectMail\Readmail;
use DirectMailTeam\DirectMail\Repository\SysDmailMaillogRepository;
use Fetch\Server;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Localization\LanguageServiceFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;

class AnalyzeBounceMailCommand extends Command
{
private ?LanguageService $languageService = null;

/**
* Configure the command by defining the name, options and arguments
*/
public function configure()
{
$this->setDescription('This command will get bounce mail from the configured mailbox')
->addOption(
'server',
's',
InputOption::VALUE_REQUIRED,
'Server URL/IP'
)
->addOption(
'port',
'p',
InputOption::VALUE_REQUIRED,
'Port number'
)
->addOption(
'user',
'u',
InputOption::VALUE_REQUIRED,
'Username'
)
->addOption(
'password',
'pw',
InputOption::VALUE_REQUIRED,
'Password'
)
->addOption(
'type',
't',
InputOption::VALUE_REQUIRED,
'Type of mailserver (imap or pop3)'
)
->addOption(
'count',
'c',
InputOption::VALUE_REQUIRED,
'Number of bounce mail to be processed'
)
//->setHelp('')
;
}

/**
* @param InputInterface $input
* @param OutputInterface $output
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
$io->title($this->getDescription());
$this->setLanguageService();

$server = '';
$port = 0;
$user = '';
$password = '';
$type = '';
$count = 0;
// check if PHP IMAP is installed
if (!extension_loaded('imap')) {
$io->error($this->languageService->getLL('scheduler.bounceMail.phpImapError'));
return Command::FAILURE;
}

if ($input->getOption('server')) {
$server = $input->getOption('server');
//$io->writeln($server);
}
if ($input->getOption('port')) {
$port = (int)$input->getOption('port');
//$io->writeln($port);
}
if ($input->getOption('user')) {
$user = $input->getOption('user');
//$io->writeln($user);
}
if ($input->getOption('password')) {
$password = $input->getOption('password');
//$io->writeln($password);
}
if ($input->getOption('type')) {
$type = $input->getOption('type');
//$io->writeln($type);
if(!in_array($type, ['imap', 'pop3'])) {
$io->warning('Type: only imap or pop3');
return Command::FAILURE;
}
}
if ($input->getOption('count')) {
$count = (int)$input->getOption('count');
//$io->writeln($count);
}

// try connect to mail server
$mailServer = $this->connectMailServer($server, $port, $type, $user, $password, $io);
if ($mailServer instanceof Server) {
// we are connected to mail server
// get unread mails
$messages = $mailServer->search('UNSEEN', $count);
if(count($messages)) {
/** @var Message $message The message object */
foreach ($messages as $message) {
// process the mail
if ($this->processBounceMail($message)) {
//$io->writeln($message->getSubject());
// set delete
$message->delete();
}
else {
$message->setFlag('SEEN');
}
}
}
// expunge to delete permanently
$mailServer->expunge();
imap_close($mailServer->getImapStream());
return Command::SUCCESS;
}
else {
return Command::FAILURE;
}

return Command::SUCCESS;
}

/**
* Process the bounce mail
* @param Message $message the message object
* @return bool true if bounce mail can be parsed, else false
*/
private function processBounceMail($message)
{
/** @var Readmail $readMail */
$readMail = GeneralUtility::makeInstance(Readmail::class);

// get attachment
$attachmentArray = $message->getAttachments();
$midArray = [];
if (is_array($attachmentArray)) {
// search in attachment
foreach ($attachmentArray as $attachment) {
$bouncedMail = $attachment->getData();
// Find mail id
$midArray = $readMail->find_XTypo3MID($bouncedMail);
if (false === empty($midArray)) {
// if mid, rid and rtbl are found, then stop looping
break;
}
}
}
else {
// search in MessageBody (see rfc822-headers as Attachments placed )
$midArray = $readMail->find_XTypo3MID($message->getMessageBody());
}

if (empty($midArray)) {
// no mid, rid and rtbl found - exit
return false;
}

// Extract text content
$cp = $readMail->analyseReturnError($message->getMessageBody());

$row = GeneralUtility::makeInstance(SysDmailMaillogRepository::class)->selectForAnalyzeBounceMail($midArray['rid'], $midArray['rtbl'], $midArray['mid']);

// only write to log table, if we found a corresponding recipient record
if (!empty($row)) {
$tableMaillog = 'sys_dmail_maillog';
/** @var Connection $connection */
$connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($tableMaillog);
try {
$midArray['email'] = $row['email'];
$insertFields = [
'tstamp' => $this->getTimestampFromAspect(),
'response_type' => -127,
'mid' => (int)$midArray['mid'],
'rid' => (int)$midArray['rid'],
'email' => $midArray['email'],
'rtbl' => $midArray['rtbl'],
'return_content' => serialize($cp),
'return_code' => (int)$cp['reason']
];
$connection->insert($tableMaillog, $insertFields);
$sql_insert_id = $connection->lastInsertId($tableMaillog);
return (bool)$sql_insert_id;
} catch (\Doctrine\DBAL\DBALException $e) {
// Log $e->getMessage();
return false;
}
}
else {
return false;
}
}

/**
* Create connection to mail server.
* Return mailServer object or false on error
*
* @param string $server
* @param int $port
* @param string $type
* @param string $user
* @param string $password
* @param SymfonyStyle $io
* @return bool|Server
*/
private function connectMailServer(string $server, int $port, string $type, string $user, string $password, SymfonyStyle $io)
{
// check if we can connect using the given data
/** @var Server $mailServer */
$mailServer = GeneralUtility::makeInstance(
Server::class,
$server,
$port,
$type
);

// set mail username and password
$mailServer->setAuthentication($user, $password);

try {
$imapStream = $mailServer->getImapStream();
return $mailServer;
} catch (\Exception $e) {
$io->error($this->languageService->getLL('scheduler.bounceMail.dataVerification').$e->getMessage());
return false;
}
}

/**
*
* @return int
*/
private function getTimestampFromAspect(): int {
$context = GeneralUtility::makeInstance(Context::class);
return $context->getPropertyFromAspect('date', 'timestamp');
}

/**
* @return void
*/
private function setLanguageService(): void {
$languageServiceFactory = GeneralUtility::makeInstance(LanguageServiceFactory::class);
$this->languageService = $languageServiceFactory->create('en'); //@TODO
$this->languageService->includeLLFile('EXT:direct_mail/Resources/Private/Language/locallang_mod2-6.xlf');
}
}
39 changes: 39 additions & 0 deletions Classes/Command/DirectmailCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php
namespace DirectMailTeam\DirectMail\Command;

use DirectMailTeam\DirectMail\Dmailer;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use TYPO3\CMS\Core\Utility\GeneralUtility;

class DirectmailCommand extends Command
{
/**
* Configure the command by defining the name, options and arguments
*/
public function configure()
{
$this->setDescription('This command invokes dmailer in order to process queued messages.');
//$this->setHelp('');
}

/**
* @param InputInterface $input
* @param OutputInterface $output
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
$io->title($this->getDescription());
/**
* The direct_mail engine
* @var $htmlmail Dmailer
*/
$htmlmail = GeneralUtility::makeInstance(Dmailer::class);
$htmlmail->start();
$htmlmail->runcron();
return Command::SUCCESS;
}
}
6 changes: 2 additions & 4 deletions Classes/Command/InvokeMailerEngineCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ public function configure()
}

/**
* Executes the command for showing sys_log entries
*
* @param InputInterface $input
* @param OutputInterface $output
*/
Expand All @@ -72,7 +70,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
// If the lock is not older than 1 day, skip:
if (filemtime($lockfile) > (time() - (60 * 60 * 24))) {
$io->warning('TYPO3 Direct Mail Cron: Aborting, another process is already running!');
return 0;
return Command::FAILURE;
} else {
$io->writeln('TYPO3 Direct Mail Cron: A .lock file was found but it is older than 1 day! Processing mails ...');
}
Expand All @@ -91,6 +89,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
$htmlmail->runcron();

unlink($lockfile);
return 0;
return Command::SUCCESS;
}
}
Loading

0 comments on commit 08b6c0a

Please sign in to comment.