Skip to content

Instantly share code, notes, and snippets.

@benjaminpick
Last active March 16, 2017 14:55
Show Gist options
  • Save benjaminpick/b0c8c4d9a0e9c219413b4c022db6ddcf to your computer and use it in GitHub Desktop.
Save benjaminpick/b0c8c4d9a0e9c219413b4c022db6ddcf to your computer and use it in GitHub Desktop.
Powermail Extension: Embed images from template into the HTML email (e.g. for images in the email footer)
<?php
/** @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher $signalSlotDispatcher */
$signalSlotDispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\SignalSlot\Dispatcher');
// Needs powermail >= 3.3.0
$signalSlotDispatcher->connect(
'In2code\Powermail\Domain\Service\SendMailService',
'sendTemplateEmailBeforeSend',
'In2code\Powermailextended\Domain\Service\SendMailService',
'manipulateMail',
FALSE
);
<?php
namespace In2code\Powermailextended\Domain\Service;
use In2code\Powermail\Domain\Model\Mail;
use TYPO3\CMS\Core\Mail\MailMessage;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use In2code\Powermail\Domain\Service\SendMailService as SendMailServicePowermail;
/**
* SendMailService
* (used for embedding the signature images)
*
* SignalSlot is declared in ext_localconf
*
*/
class SendMailService {
const TAG_START = '<img src="';
const TAG_END = '"';
const PATH = 'EXT:powermail_optigem/Resources/Public/Images/Signature/';
const ALLOWED_PATH = 'EXT:powermail_optigem/Resources/Public/';
/**
* Manipulate message object short before powermail send the mail
*
* @param MailMessage $message
* @param array $email
* @param SendMailServicePowermail $sendMailService
*/
public function manipulateMail($message, &$email, SendMailServicePowermail $sendMailService) {
$body = $message->getBody();
$path = self::PATH;
$len_tag_start = mb_strlen(self::TAG_START);
$len_tag_end = mb_strlen(self::TAG_END);
$start = mb_stripos($body, self::TAG_START);
while ($start !== false) {
$end = mb_strpos($body, self::TAG_END, $start + $len_tag_start + 1);
$filename = mb_substr($body, $start + $len_tag_start, $end - $start - $len_tag_start - $len_tag_end + 1);
if (!$this->str_starts_with($filename, 'cid:')) {
if ($this->str_starts_with($filename, 'http://') || $this->str_starts_with($filename, 'https://'))
{
if (GeneralUtility::isOnCurrentHost($filename)) {
$host = GeneralUtility::getIndpEnv('TYPO3_REQUEST_HOST');
$site_path = dirname(GeneralUtility::getIndpEnv('SCRIPT_FILENAME'));
$fileAbs = $site_path . mb_substr($filename, mb_strlen($host));
}
}
else
{
$fileAbs = GeneralUtility::getFileAbsFileName($path . $filename);
}
if ($this->validateFilename($fileAbs)) {
$embedId = $message->embed(\Swift_Image::fromPath($fileAbs));
if ($embedId) {
$search = self::TAG_START . $filename . self::TAG_END;
$replace = self::TAG_START . $embedId . self::TAG_END;
$body = str_replace($search, $replace, $body);
}
}
}
$start = mb_stripos($body, self::TAG_START, $start + 1);
}
$message->setBody($body, 'text/html');
}
protected function str_starts_with($haystack, $needle) {
$length = mb_strlen($needle);
return mb_substr($haystack, 0, $length) === $needle;
}
protected function validateFilename($filename) {
if (!file_exists($filename))
return false;
// Security: only images may be attached
$allowedExtensions = array(
'png',
'jpg',
'jpeg',
'gif',
);
$ext = pathinfo($filename, PATHINFO_EXTENSION);
if (!in_array(strtolower($ext), $allowedExtensions))
return false;
// Security: Check if path is within ALLOWED_PATH
$allowed = @realpath(GeneralUtility::getFileAbsFileName(self::ALLOWED_PATH));
if (!$allowed)
return false;
$r1 = @realpath($filename);
if (!$this->str_starts_with($r1, $allowed))
return false;
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment