Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
barryvdh committed Feb 22, 2021
0 parents commit fb49e27
Show file tree
Hide file tree
Showing 13 changed files with 459 additions and 0 deletions.
30 changes: 30 additions & 0 deletions Helper/Data.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Fruitcake\EmailAdvancedConfig\Helper;


use Fruitcake\EmailAdvancedConfig\Model\Config\Source\SmtpTransportType;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
use Magento\Store\Model\ScopeInterface;


class Data extends AbstractHelper
{
const CONFIG_PATH = 'fruitcake_email_advanced/';

public function isEnabled(): bool
{
return $this->getConfig('smtp/transport') === SmtpTransportType::TRANSPORT_SMTP;
}

/**
* @param string $code
*
* @return mixed
*/
public function getConfig($code = '')
{
return $this->scopeConfig->getValue(self::CONFIG_PATH . $code, ScopeInterface::SCOPE_STORE, null);
}
}
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2021 Fruitcake

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
32 changes: 32 additions & 0 deletions Model/Config/Source/SmtpAuthType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Fruitcake\EmailAdvancedConfig\Model\Config\Source;

use Fruitcake\EmailAdvancedConfig\Model\Config\AdvancedConfig;

/**
* Option provider for custom media URL type
*/
class SmtpAuthType implements \Magento\Framework\Data\OptionSourceInterface
{
/**
* The the possible Auth types
*
* @codeCoverageIgnore
* @return array
*/
public function toOptionArray(): array
{
return [
['value' => 'none', 'label' => 'NONE'],
['value' => 'plain', 'label' => 'PLAIN'],
['value' => 'login', 'label' => 'LOGIN'],
['value' => 'crammd5', 'label' => 'CRAM-MD5 (Require laminas/laminas-crypt)']
];
}
}
31 changes: 31 additions & 0 deletions Model/Config/Source/SmtpSslType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Fruitcake\EmailAdvancedConfig\Model\Config\Source;

use Fruitcake\EmailAdvancedConfig\Model\Config\AdvancedConfig;

/**
* Option provider for custom media URL type
*/
class SmtpSslType implements \Magento\Framework\Data\OptionSourceInterface
{
/**
* The the possible Auth types
*
* @codeCoverageIgnore
* @return array
*/
public function toOptionArray(): array
{
return [
['value' => 'none', 'label' => 'None'],
['value' => 'ssl', 'label' => 'SSL'],
['value' => 'tls', 'label' => 'TLS'],
];
}
}
33 changes: 33 additions & 0 deletions Model/Config/Source/SmtpTransportType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Fruitcake\EmailAdvancedConfig\Model\Config\Source;

use Fruitcake\EmailAdvancedConfig\Model\Config\AdvancedConfig;

/**
* Option provider for custom media URL type
*/
class SmtpTransportType implements \Magento\Framework\Data\OptionSourceInterface
{
public const TRANPORT_SENDMAIL = 'sendmail';
public const TRANSPORT_SMTP = 'smtp';

/**
* The the possible Auth types
*
* @codeCoverageIgnore
* @return array
*/
public function toOptionArray(): array
{
return [
['value' => self::TRANPORT_SENDMAIL, 'label' => 'Sendmail (Magento default)'],
['value' => self::TRANSPORT_SMTP, 'label' => 'SMTP Configuration'],
];
}
}
148 changes: 148 additions & 0 deletions Model/SmtpTransport.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Fruitcake\EmailAdvancedConfig\Model;

use Fruitcake\EmailAdvancedConfig\Helper\Data;
use Laminas\Mail\Transport\Smtp;
use Laminas\Mail\Transport\SmtpOptions;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Exception\MailException;
use Magento\Framework\Mail\MessageInterface;
use Magento\Framework\Mail\TransportInterface;
use Magento\Framework\Phrase;
use Magento\Store\Model\ScopeInterface;
use Laminas\Mail\Message;
use Laminas\Mail\Transport\Sendmail;

/**
* Class that responsible for filling some message data before transporting it.
* @see \Laminas\Mail\Transport\Smtp is used for transport
* @see \Magento\Email\Model\Transport for the original Magento implementation. This overrides the construct
*/
class SmtpTransport implements TransportInterface
{
/**
* Configuration path to source of Return-Path and whether it should be set at all
* @see \Magento\Config\Model\Config\Source\Yesnocustom to possible values
*/
const XML_PATH_SENDING_SET_RETURN_PATH = 'system/smtp/set_return_path';

/**
* Configuration path for custom Return-Path email
*/
const XML_PATH_SENDING_RETURN_PATH_EMAIL = 'system/smtp/return_path_email';

/**
* Whether return path should be set or no.
*
* Possible values are:
* 0 - no
* 1 - yes (set value as FROM address)
* 2 - use custom value
*
* @var int
*/
private $isSetReturnPath;

/**
* @var string|null
*/
private $returnPathValue;

/**
* @var Sendmail
*/
private $laminasTransport;

/**
* @var MessageInterface
*/
private $message;

/** @var Data */
private $helper;

/**
* @param MessageInterface $message Email message object
* @param ScopeConfigInterface $scopeConfig Core store config
* @param null|string|array|\Traversable $parameters Config options for sendmail parameters
*/
public function __construct(
MessageInterface $message,
ScopeConfigInterface $scopeConfig,
Data $helper,
$parameters = null
) {
$this->isSetReturnPath = (int) $scopeConfig->getValue(
self::XML_PATH_SENDING_SET_RETURN_PATH,
ScopeInterface::SCOPE_STORE
);
$this->returnPathValue = $scopeConfig->getValue(
self::XML_PATH_SENDING_RETURN_PATH_EMAIL,
ScopeInterface::SCOPE_STORE
);
$this->helper = $helper;

$this->message = $message;

// When not enabled, fall back to Sendmail transport
if (! $this->helper->isEnabled()) {
throw new \RuntimeException('Should be enabled');
$this->laminasTransport = new Sendmail($parameters);
return;
}

$options = [
'name' => 'localhost',
'host' => $this->helper->getConfig('smtp/host'),
'port' => $this->helper->getConfig('smtp/port'),
'connection_class' => $this->helper->getConfig('smtp/auth'),
'connection_config' => [
'username' => $this->helper->getConfig('smtp/username'),
'password' => $this->helper->getConfig('smtp/password'),
]
];

$ssl = $this->helper->getConfig('smtp/ssl');

if ($ssl && $ssl !== 'none') {
$connectionConfig['ssl'] = $ssl;
}

$this->laminasTransport = new Smtp(new SmtpOptions($options));
}

/**
* @inheritdoc
*/
public function sendMessage()
{
try {
$laminasMessage = Message::fromString($this->message->getRawMessage())->setEncoding('utf-8');
if (2 === $this->isSetReturnPath && $this->returnPathValue) {
$laminasMessage->setSender($this->returnPathValue);
} elseif (1 === $this->isSetReturnPath && $laminasMessage->getFrom()->count()) {
$fromAddressList = $laminasMessage->getFrom();
$fromAddressList->rewind();
$laminasMessage->setSender($fromAddressList->current()->getEmail());
}

$this->laminasTransport->send($laminasMessage);
} catch (\Exception $e) {
throw new MailException(new Phrase($e->getMessage()), $e);
}
}

/**
* @inheritdoc
*/
public function getMessage()
{
return $this->message;
}
}
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Magento2 Advanced Email

Adds SMTP User/Pass/Authentication to the default Magento2 smtp, nothing else.

## Install

```
composer require fruitcake/magento2-email-advanced-config
php bin/magento module:enable Fruitcake_EmailAdvancedConfig
php bin/magento setup:upgrade
```

## License

MIT
39 changes: 39 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"name": "fruitcake/magento2-email-advanced-config",
"description": "Magento2 Advanced SMTP Configuration",
"keywords": [
"magento",
"magento2",
"smtp",
"email"
],
"license": [
"MIT"
],
"type": "magento2-module",
"version": "1.0.0",
"authors": [
{
"name": "Fruitcake",
"email": "info@fruitcake.nl"
}
],
"require": {
"php": "^7"
},
"autoload": {
"files": [
"registration.php"
],
"psr-4": {
"Fruitcake\\EmailAdvancedConfig\\": ""
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
}
}

0 comments on commit fb49e27

Please sign in to comment.