diff --git a/.buildpath b/.buildpath
new file mode 100644
index 0000000..58a40b7
--- /dev/null
+++ b/.buildpath
@@ -0,0 +1,219 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
index a67d42b..52b47ef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,5 @@ composer.phar
# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control
# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
# composer.lock
+/composer.lock
+/set-local-test-env.sh
diff --git a/.project b/.project
new file mode 100644
index 0000000..51153c6
--- /dev/null
+++ b/.project
@@ -0,0 +1,33 @@
+
+
+ php-email
+
+
+
+
+
+ org.eclipse.php.composer.core.builder.buildPathManagementBuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+ org.eclipse.dltk.core.scriptbuilder
+
+
+
+
+
+ org.eclipse.php.core.PHPNature
+ org.eclipse.wst.common.project.facet.core.nature
+
+
diff --git a/.settings/org.eclipse.php.composer.core.prefs b/.settings/org.eclipse.php.composer.core.prefs
new file mode 100644
index 0000000..c350800
--- /dev/null
+++ b/.settings/org.eclipse.php.composer.core.prefs
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+include_path=0;/php-email/src
+org.eclipse.php.composer.corebuildpath.includes.excludes=\n
diff --git a/.settings/org.eclipse.php.core.prefs b/.settings/org.eclipse.php.core.prefs
new file mode 100644
index 0000000..5daaa54
--- /dev/null
+++ b/.settings/org.eclipse.php.core.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+include_path=0;/php-email/src
diff --git a/.settings/org.eclipse.php.ui.prefs b/.settings/org.eclipse.php.ui.prefs
new file mode 100644
index 0000000..9a3362f
--- /dev/null
+++ b/.settings/org.eclipse.php.ui.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+org.eclipse.php.ui.text.custom_code_templates=
diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..54838ab
--- /dev/null
+++ b/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/.settings/org.eclipse.wst.validation.prefs b/.settings/org.eclipse.wst.validation.prefs
new file mode 100644
index 0000000..39a5ef6
--- /dev/null
+++ b/.settings/org.eclipse.wst.validation.prefs
@@ -0,0 +1,2 @@
+disabled=06vendor
+eclipse.preferences.version=1
diff --git a/README.md b/README.md
index 0f4aa98..4549c15 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,388 @@
# php-email
-Provides an object-oriented way to send and queue emails
+Provides an object-oriented way to send and queue emails.
+
+There is a need to send e-mails in almost all projects, e.g. for user registration or
+password reset functions. Most e-mails sent are very easy. Sophisticated features
+like PGP encryption etc is not required. This library offers a way to create
+such e-mails without setting up the PHPMailer (the underlying library), to send
+multiple e-mails and even to defer sending e-mail sending by using a queue backed
+by a database - and all in an object-oriented way.
+
+Features are:
+
+* Encapsulating SMTP settings in an `EmailQueue` object.
+* Reuse a mailer object for multiple e-mails
+* Sending HTML and TEXT e-mails
+* Embedding pictures and attaching files
+* Enqueueing mails in a database backend
+* Prefixing subject lines automatically
+* Easily create compatible e-mail addresses including the address name
+* E-mail queue will try to send an e-mail multiple times before failing
+* Ability to set a "Mail Mode". Mail Modes can BCC, reroute or even block e-mails completely
+ which can be useful in development or acceptance environments.
+
+# License
+This project is licensed under [GNU LGPL 3.0](LICENSE.md).
+
+# Installation
+
+## By Composer
+
+```
+composer install technicalguru/email
+```
+
+## By Package Download
+You can download the source code packages from [GitHub Release Page](https://github.com/technicalguru/php-email/releases)
+
+# How to use it
+
+## Create Main Configuration Object
+
+The central class for configuration is the `EmailConfig`. It holds all necessary information.
+Let's start with the basic skeleton:
+
+```
+
+use TgEmail\EmailConfig;
+
+$config = new EmailConfig();
+$config->setTimezone('Europe/Berlin');
+$config->setDefaultSender('John Doe ');
+$config->setSubjectPrefix('[MyAppName] ');
+$config->setDebugAddress('admin@example.com');
+```
+
+The lines above create the configuration and tells it to use the timezone `Europe/Berlin` when it needs
+to create timestamps. This is required mainly when e-mails are queued and the timestamp needs to be
+recorded. This value is optional and defaults to `UTC`.
+
+Next, a default sender address is configured. The default sender will be used when a specific
+e-mail to be sent does not define a sender address. Creating e-mail addresses is explained further below.
+
+The subject prefix is used on every e-mail to be sent later. Subjects will be prefixed with this string. The
+default is `NULL` and will not modify the subject.
+
+A debug address is required only when you need to send a test mail.
+
+## Create SMTP Configuration
+
+We still need to tell where our SMTP server is located. So this is how you set these values:
+
+```
+use TgEmail\Config\SmtpConfig;
+
+$host = 'smtp.example.com;
+$port = 587;
+$auth = TRUE;
+$username = 'mySmtpUser';
+$password = 'mySmtpPassword';
+$secureOption = 'starttls';
+
+$smtpConfig = new SmtpConfig($host, $port, $auth, $username, $password, $secureOption);
+$config->setSmtpConfig($smtpConfig);
+```
+
+Most options are self-explaining. `$auth` tells underlying PHPMailer whether to authenticate with given
+user credentials. `$secureOption` is defined by `PHPMailer` and shall have value `smtps` or `starttls`.
+See the PHPMailer documentation for further information.
+
+All properties can be set by using a setter:
+
+```
+use TgEmail\Config\SmtpConfig;
+
+$smtpConfig = new SmtpConfig();
+$smtpConfig->setHost('smtp.example.com');
+$smtpConfig->setPort(587);
+
+// continue setup...
+```
+
+Authentication credentials can also be set by using the `\TgUtils\Auth\CredentialsProvider` interface from
+`technicalguru/utils` package:
+
+```
+// Define here your provider
+$provider = ...;
+
+// Tell SMTP config
+$smtpConfig->setCredentialsProvider($provider);
+```
+
+## Create the Main MailQueue object
+
+Now it's time to create our central `MailQueue` object:
+
+```
+use TgEmail\EmailQueue;
+
+$mailer = new EmailQueue($config);
+```
+
+You are ready send your first e-mail.
+
+## Send a Test E-Mail
+
+There is a fast and easy way to check whether your setup works correctly:
+
+```
+$email = $mailer->createTestMail();
+$rc = $mailer->send($email);
+```
+
+## Send an E-Mail
+
+We have setup the minimum requirements to send an e-mail:
+
+```
+use TgEmail\Email;
+
+$email = new Email();
+$email
+ ->setSubject('Hello World')
+ ->addTo('john.doe@example.com', 'John Doe')
+ ->addBcc('jane.doe@example.com')
+ ->setReplyTo('my-support@example.com')
+ ->setBody(Email::TEXT, 'The text e-mail body')
+ ->setBody(Email::HTML, 'The HTML e-mail body
');
+
+// Will return FALSE when sending fails
+$rc = $mailer->send($email);
+```
+
+That's it. The code snippet above is all you would need in your application code in order to send e-mails.
+Configuration and setup shall be buried somewhere in your infrastructure setup.
+
+## Hot to add Attachments or embed Images
+
+Attaching files or embedding images is simple. You will need to have the file available and readable
+on the filesystem:
+
+```
+use TgEmail\Attachment;
+
+$myFile = new Attachment(Attachment::ATTACHED, 'file.pdf', NULL, '/local/path/to/file.pdf', 'application/pdf');
+$myImage = new Attachment(Attachment::EMBEDDED, 'img.png', 'img1', '/local/path/to/img.png', 'image/png');
+
+$email
+ ->addAttachment($myFile)
+ ->addAttachment($myImage);
+```
+
+Note the third parameter of embedded images. It defines a unique ID within your HTML email which you can reference by
+
+```
+// Using the embedded image
+$myHTML = '';
+```
+
+The `MailQueue` will leave all your attachments untouched on your filesystem. However, sometimes you may wish to get rid
+of the file after you sent the e-mail. The constructor takes two additional arguments:
+
+```
+$myFile = new Attachment(Attachment::ATTACHED, $filename, $cid, $path, $mimeType, TRUE, TRUE);
+```
+
+The first boolean will trigger the file to be deleted after the e-mail was sent successfully. The second boolean tells
+whether the file can be deleted when sending failed. Using these parameters you don't need to take care
+about temporary files anymore. Especially when it comes to queueing and deferred sending.
+
+## Mail Modes
+
+`MailQueue` supports so-called Mail Modes. They tell the mailer object how to generally treat e-mails. This comes
+comfortable when you're either testing a setup, when you are in an environment that has real e-mail addresses (such as User Acceptance Test environments) or when actually sending out e-mails doesn't make much sense.
+
+These modes are available:
+
+* `EmailQueue::DEFAULT` - This is the normal operation. All e-mails are sent as defined.
+* `EmailQueue::BLOCK` - This will prevent any mail to be sent or queued. The return code is always TRUE.
+* `EmailQueue::REROUTE` - All e-mails will be sent to another address, usually an admin or developer address and the
+ defined recipients of the e-mail are ignored.
+* `EmailQueue::BCC` - The e-mails will be sent to their intended recipients but additional addresses are set on BCC.
+
+### Blocking all E-Mails
+
+Blocking all e-mails to be sent or queued is quite easy:
+
+```
+$mailer->setMailMode(EmailQueue::BLOCK);
+```
+
+The same method can be used on the central `EmailConfig` object.
+
+### Rerouting all E-Mails
+
+You need a `RerouteConfig` configuration to be set in the main configuration. You can set this up-front when creating the
+config object, or alltogether when setting the mail mode:
+
+```
+use TgEmail\Config\RerouteConfig;
+
+// Create the config
+$subjectPrefix = '[Rerouted]';
+$recipients = array('my-dev-account@example.com');
+$rerouteConfig = new RerouteConfig($subjectPrefix, $recipients);
+
+// And set the mail mode
+$mailer->setMailMode(EmailQueue::REROUTE, $rerouteConfig);
+```
+
+### Set a Developer as BCC on all sent E-mails
+
+You need a `BccConfig` configuration to be set in the main configuration. You can set this up-front when creating the
+config object, or alltogether when setting the mail mode:
+
+```
+use TgEmail\Config\BccConfig;
+
+// Create the config
+$recipients = array('my-dev-account@example.com');
+$bccConfig = new BccConfig($recipients);
+
+// And set the mail mode
+$mailer->setMailMode(EmailQueue::BCC, $bccConfig);
+```
+
+## Queue E-Mails to be sent later
+
+One drawback of sending out e-mails directly from application code is the that it is time-consuming. Your
+user needs to wait for the sending to complete before she/he can see any response from your application.
+Queueing e-mails is the solution as sending is deferred (preferrable to a cron job) and the user receives
+her/his application response fast.
+
+You will need a [`TgDatabase\Database`](https://github.com/technicalguru/php-database/blob/main/src/TgDatabase/Database.php)
+object to queue e-mails. Otherwise, `EmailQueue` will throw exceptions when you try to queue e-mails. Please refer
+to the [`TgDatabase\Database`](https://github.com/technicalguru/php-database/) documentation about how to create
+the `Database` object. Setup the according `EmailsDAO` and `EmailQueue` as follows:
+
+```
+use TgEmail\EmailsDAO;
+
+$dao = new EmailsDAO($database);
+$mailer = new EmailQueue($config, $dao);
+```
+
+The mailer will automatically create the queue table if it does not exist.
+
+Once, the `EmailsDAO` is available, you can easily queue e-mails:
+
+```
+// Create your email object here
+$email = ...
+
+// Queue it. Will return FALSE when sending fails
+$rc = $mailer->queue($email);
+```
+
+## Processing the E-Mail Queue
+
+You can process the queue in another call or during a cronjob:
+
+```
+$mailer->processQueue($maxSeconds);
+```
+
+The argument `$maxSeconds` will ensure that the processing stops when the time limit has been reached.
+The argument is optional and defaults to 60 seconds.
+
+## How to Create an E-mail Address
+
+There are multiple ways to create e-mail addresses. All mailing components use an `EmailAddress` object.
+You can use this object as an argument whereever e-mail addresses are expected. Several ways exist
+to create such an object.
+
+```
+// From a string
+$address = EmailAddress::from('john.doe@example.com');
+$address = EmailAddress::from('');
+$address = EmailAddress::from('John Doe ');
+
+// From email string and name
+$address = EmailAddress::from('john.doe@example.com', 'John Doe');
+
+// From another object
+$obj = new \stdClass;
+$obj->name = 'John Doe';
+$obj->email = 'john.doe@example.com';
+$address = EmailAddress::from($obj);
+
+// From another EmailAddress
+$address = EmailAddress::from($anotherEmailAddressObject);
+```
+
+This means that you can use these flavours when creating e-mails:
+
+```
+$email->addTo('John Doe ');
+$email->addTo('john.doe@example.com', 'John Doe');
+$email->addTo(array('John Doe ', $anotherEmailAddressObject, $obj);
+```
+
+## Creating Configuration Objects from Objects, Arrays or JSON strings
+
+The configuration objects introduced above can also be created using JSON strings, objects or associative arrays.
+The following snippets describe the JSON objects in short notation.
+
+```
+SmtpConfig:
+-----------
+{
+ "host": "www.example.com",
+ "port": 587,
+ "debugLevel": 0,
+ "auth": true,
+ "secureOption": "starttls",
+ "charset": "utf8",
+ "credentials": {
+ "user": "username",
+ "pass": "password"
+ }
+},
+
+RerouteConfig:
+--------------
+{
+ "recipients": "hans.mustermann@example.com",
+ "subjectPrefix": "[Rerouted]"
+},
+
+BccConfig:
+----------
+{
+ "recipients": "hans.mustermann@example.com"
+},
+
+EmailConfig:
+------------
+{
+ "timezone": "Europe\/Berlin",
+ "mailMode": "default",
+ "smtpConfig": {... see above ...},
+ "rerouteConfig": {... see above ...},
+ "bccConfig": {... see above ...},
+ "debugAddress": "john.doe@example.com",
+ "defaultSender": "jane.doe@example.com",
+ "subjectPrefix": "[PHPUnitTest] "
+}
+```
+
+Each of the configuration classes provide a static `from()` method that take these types as an argument and return the
+configuration object itself:
+
+```
+$smtpConfig = SmtpConfig::from($jsonStringOrObjectOrAssocArray);
+$rerouteConfig = RerouteConfig::from($jsonStringOrObjectOrAssocArray);
+$bccConfig = BccConfig::from($jsonStringOrObjectOrAssocArray);
+$emailConfig = EmailConfig::from($jsonStringOrObjectOrAssocArray);
+```
+
+# Development Notes
+
+Most PHPUnit tests will not be executed when there is no SMTP server or database available. The unit tests will check
+for environment variable `EMAIL_TEST_SMTP` and `EMAIL_DATABASE`. There is a bash script available,
+[`set-test-env.sh`](https://github.com/technicalguru/php-email/blob/main/set-test-env.sh) that creates those
+variables for you. Copy it to e.g. `set-local-test-env.sh` and follow instructions in the file.
+
+# Contribution
+Report a bug, request an enhancement or pull request at the [GitHub Issue Tracker](https://github.com/technicalguru/php-email/issues).
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..b5230cc
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,36 @@
+{
+ "name" : "technicalguru/email",
+ "description" : "Provides an object-oriented way to send and queue emails",
+ "type" : "library",
+ "keywords" : [
+ "email",
+ "mail",
+ "mailqueue",
+ "queue"
+ ],
+ "license" : "LGPL-3.0-or-later",
+ "authors" : [{
+ "name" : "technicalguru",
+ "email" : "github@ralph-schuster.eu"
+ }
+ ],
+ "require" : {
+ "php" : ">=7.0.0",
+ "technicalguru/utils" : "~1",
+ "phpmailer/phpmailer" : "^6.1",
+ "symfony/polyfill-mbstring" : "^1.20",
+ "technicalguru/database" : "~0",
+ "phpunit/phpunit": "^9.4"
+ },
+ "autoload" : {
+ "psr-4" : {
+ "TgEmail\\" : "src/TgEmail/",
+ "" : ""
+ },
+ "psr-0" : {
+ "TgEmail" : "src/TgEmail"
+ }
+ },
+ "require-dev" : {
+ }
+}
diff --git a/set-test-env.sh b/set-test-env.sh
new file mode 100755
index 0000000..12f772d
--- /dev/null
+++ b/set-test-env.sh
@@ -0,0 +1,70 @@
+#!/bin/bash
+
+#######################################################
+#
+# TEST HOWTO
+#
+# Copy this file to e.g. set-local-test-env.sh and
+# set the various variables below. Then source the
+# file on you bash shell:
+#
+# ~/git/php-email$ . ./set-local-test-env.sh
+#
+# and start the PHP Unit tests:
+#
+# ~/git/php-email$ ./vendor/bin/phpunit tests
+#
+#######################################################
+
+# Set this to 2 if your tests fail (will show SMTP debug)
+DEBUG_LEVEL=0
+
+# Timezone for dates
+TIMEZONE="Europe\\/Berlin"
+
+# The email address that all test emails shall be sent to
+TARGET_EMAIL=john.doe@example.com
+
+# The default sender address
+SENDER_EMAIL=jane.doe@example.com
+
+# The SMTP information
+SMTP_HOST=www.example.com
+SMTP_PORT=587
+SMTP_AUTH=true
+SMTP_USER=username
+SMTP_PASS=password
+SMTP_SECURE=starttls
+
+# The Debug Address (for test mail feature
+DEBUG_EMAIL=$TARGET_EMAIL
+
+# The BCC email address (BCC mail mode)
+BCC_EMAIL=hans.mustermann@example.com
+
+# The Reroute email address (REROUTE mail mode)
+REROUTE_EMAIL=$BCC_EMAIL
+
+# The database information
+DB_HOST=localhost
+DB_PORT=3306
+DB_NAME=databasename
+DB_USER=username
+DB_PASS=password
+DB_PREFIX=phpunittest_
+
+################ DO NOT EDIT FROM HERE ON #############
+BCC_CONFIG="{\"recipients\":\"${BCC_EMAIL}\"}"
+REROUTE_CONFIG="{\"recipients\":\"${REROUTE_EMAIL}\",\"subjectPrefix\":\"[Rerouted]\"}"
+
+SMTP_CONFIG="{\"host\":\"${SMTP_HOST}\",\"port\":${SMTP_PORT},\"debugLevel\":${DEBUG_LEVEL},\"auth\":${SMTP_AUTH},\"credentials\":{\"user\":\"${SMTP_USER}\",\"pass\":\"${SMTP_PASS}\"},\"secureOption\":\"${SMTP_SECURE}\",\"charset\":\"utf8\"}"
+
+EMAIL_TEST_SMTP="{\"timezone\":\"${TIMEZONE}\",\"mailMode\":\"default\",\"targetAddress\":\"${TARGET_EMAIL}\", \"smtpConfig\":${SMTP_CONFIG},\"rerouteConfig\":${REROUTE_CONFIG},\"bccConfig\":${BCC_CONFIG},\"debugAddress\":\"${DEBUG_EMAIL}\",\"defaultSender\":\"${SENDER_EMAIL}\",\"subjectPrefix\":\"[PHPUnitTest] \"}"
+EMAIL_DATABASE="{\"host\":\"${DB_HOST}\",\"port\":${DB_PORT},\"dbname\":\"${DB_NAME}\",\"user\":\"${DB_USER}\",\"pass\":\"${DB_PASS}\",\"tablePrefix\":\"${DB_PREFIX}\"}"
+
+export EMAIL_TEST_SMTP
+export EMAIL_DATABASE
+
+
+
+
diff --git a/src/TgEmail/Attachment.php b/src/TgEmail/Attachment.php
new file mode 100644
index 0000000..c91db4b
--- /dev/null
+++ b/src/TgEmail/Attachment.php
@@ -0,0 +1,52 @@
+The actual content of the attachment must be available as a file.
+ * @author ralph
+ *
+ */
+class Attachment {
+
+ public const ATTACHED = 'default';
+ public const EMBEDDED = 'embedded';
+
+ /** The embedding type */
+ public $type;
+ public $name;
+ public $cid;
+ public $path;
+ public $mimeType;
+ public $deleteAfterSent;
+ public $deleteAfterFailed;
+
+ /**
+ * Constructor.
+ * @param string $type - the embedding type of this attachment
+ * @param string $name - the name of the attachment as to be used in email
+ * @param string $path - the path to the local file
+ * @param boolean deleteAfterSent - whether to delete the file when the mail was sent
+ * @param boolean deleteAfterFailed - whether to delete the file when sending of the email failed (requires deleteAfterSent = TRUE)
+ */
+ public function __construct($type, $name, $cid, $path, $mimeType, $deleteAfterSent = false, $deleteAfterFailed = false) {
+ $this->type = $type;
+ $this->name = $name;
+ $this->cid = $cid;
+ $this->path = $path;
+ $this->deleteAfterSent = $deleteAfterSent;
+ $this->deleteAfterFailed = $deleteAfterFailed;
+ }
+
+ public static function from($a) {
+ if (is_object($a)) {
+ if (is_a($a, 'TgEmail\\Attachment')) {
+ return $a;
+ }
+ return new Attachment($a->type, $a->name, $a->cid, $a->path, $a->mimeType, $a->deleteAfterSent, $a->deleteAfterFailed);
+ }
+ throw new EmailException('Cannot convert attachment');
+ }
+}
+
diff --git a/src/TgEmail/Config/BccConfig.php b/src/TgEmail/Config/BccConfig.php
new file mode 100644
index 0000000..e5a9f44
--- /dev/null
+++ b/src/TgEmail/Config/BccConfig.php
@@ -0,0 +1,61 @@
+recipients = array();
+ $this->addRecipients($recipients);
+ }
+
+ public function getRecipients() {
+ return $this->recipients;
+ }
+
+ public function addRecipients($address, $name = NULL) {
+ if (is_array($address)) {
+ foreach ($address AS $a) {
+ $this->addRecipients($a);
+ }
+ } else if (is_string($address)) {
+ $this->recipients[] = EmailAddress::from($address, $name);
+ } else if (is_object($address)) {
+ $this->recipients[] = EmailAddress::from($address);
+ } else {
+ throw new EmailException('Cannot add recipient(s)');
+ }
+ return $this;
+ }
+
+ public static function from($config) {
+ if (is_array($config)) {
+ $config = json_decode(json_encode($config));
+ } else if (is_string($config)) {
+ $config = json_decode($config);
+ }
+ if (is_object($config)) {
+ $rc = new BccConfig();
+ if (isset($config->recipients)) {
+ $rc->addRecipients($config->recipients);
+ }
+ return $rc;
+ }
+ throw new EmailException('Cannot create BccConfig object from given config');
+ }
+
+}
+
diff --git a/src/TgEmail/Config/RerouteConfig.php b/src/TgEmail/Config/RerouteConfig.php
new file mode 100644
index 0000000..496df5c
--- /dev/null
+++ b/src/TgEmail/Config/RerouteConfig.php
@@ -0,0 +1,74 @@
+subjectPrefix = $subjectPrefix;
+ $this->recipients = array();
+ $this->addRecipients($recipients);
+ }
+
+ public function getSubjectPrefix() {
+ return $this->subjectPrefix;
+ }
+
+ public function setSubjectPrefix($prefix) {
+ $this->subjectPrefix = $prefix;
+ }
+
+ public function getRecipients() {
+ return $this->recipients;
+ }
+
+ public function addRecipients($address, $name = NULL) {
+ if (is_array($address)) {
+ foreach ($address AS $a) {
+ $this->addRecipients($a);
+ }
+ } else if (is_string($address)) {
+ $this->recipients[] = EmailAddress::from($address, $name);
+ } else if (is_object($address)) {
+ $this->recipients[] = EmailAddress::from($address);
+ } else {
+ throw new EmailException('Cannot add recipient(s)');
+ }
+ return $this;
+ }
+
+ public static function from($config) {
+ if (is_array($config)) {
+ $config = json_decode(json_encode($config));
+ } else if (is_string($config)) {
+ $config = json_decode($config);
+ }
+ if (is_object($config)) {
+ $rc = new RerouteConfig();
+ if (isset($config->recipients)) {
+ $rc->addRecipients($config->recipients);
+ }
+ if (isset($config->subjectPrefix)) {
+ $rc->setSubjectPrefix($config->subjectPrefix);
+ }
+ return $rc;
+ }
+ throw new EmailException('Cannot create RerouteConfig object from given config');
+ }
+
+}
+
diff --git a/src/TgEmail/Config/SmtpConfig.php b/src/TgEmail/Config/SmtpConfig.php
new file mode 100644
index 0000000..23d4a1d
--- /dev/null
+++ b/src/TgEmail/Config/SmtpConfig.php
@@ -0,0 +1,189 @@
+host = $host;
+ $this->port = $port;
+ $this->auth = $auth;
+ $this->setCredentials($username, $password);
+ $this->secureOption = $secureOption;
+ $this->charset = $charset;
+ }
+
+ public function getHost() {
+ return $this->host;
+ }
+
+ public function setHost($host) {
+ $this->host = $host;
+ return $this;
+ }
+
+ public function getPort() {
+ return $this->port;
+ }
+
+ public function setPort($port) {
+ $this->port = $port;
+ return $this;
+ }
+
+ public function getDebugLevel() {
+ return $this->debugLevel;
+ }
+
+ public function setDebugLevel($level) {
+ $this->debugLevel = $level;
+ return $this;
+ }
+
+ public function isAuth() {
+ return $this->auth;
+ }
+
+ public function setAuth($auth) {
+ $this->auth = $auth;
+ return $this;
+ }
+
+ public function getSecureOption() {
+ return $this->secureOption;
+ }
+
+ public function setSecureOption($option) {
+ $this->secureOption = $option;
+ return $this;
+ }
+
+ public function getUsername() {
+ return $this->getCredentialsProvider()->getUsername();
+ }
+
+ public function getPassword() {
+ return $this->getCredentialsProvider()->getPassword();
+ }
+
+ public function setCredentials($username, $password) {
+ $this->setCredentialsProvider(new DefaultCredentialsProvider($username, $password));
+ return $this;
+ }
+
+ public function getCredentialsProvider() {
+ return $this->credentialsProvider;
+ }
+
+ public function setCredentialsProvider(CredentialsProvider $provider) {
+ $this->credentialsProvider = $provider;
+ return $this;
+ }
+
+ public function getCharset() {
+ return $this->charset;
+ }
+
+ public function setCharset($charset) {
+ $this->charset = $charset;
+ return $this;
+ }
+
+ public static function from($config) {
+ if (is_array($config)) {
+ $config = json_decode(json_encode($config));
+ } else if (is_string($config)) {
+ $config = json_decode($config);
+ }
+ if (is_object($config)) {
+ $rc = new SmtpConfig();
+ if (isset($config->host)) {
+ $rc->setHost($config->host);
+ }
+ if (isset($config->port)) {
+ $rc->setPort($config->port);
+ }
+ if (isset($config->debugLevel)) {
+ $rc->setDebugLevel($config->debugLevel);
+ }
+ if (isset($config->auth)) {
+ $rc->setAuth($config->auth);
+ }
+ if (isset($config->credentialsProvider)) {
+ if (is_a($config->credentialsProvider, 'TgUtils\Auth\CredentialsProvider')) {
+ $rc->setCredentialsProvider($config->credentialsProvider);
+ } else if (is_object($config->credentialsProvider)) {
+ $username = NULL;
+ $password = NULL;
+ if (isset($config->credentialsProvider->username)) {
+ $username = $config->credentialsProvider->username;
+ }
+ if (isset($config->credentialsProvider->user)) {
+ $username = $config->credentialsProvider->user;
+ }
+ if (isset($config->credentialsProvider->password)) {
+ $password = $config->credentialsProvider->password;
+ }
+ if (isset($config->credentialsProvider->passwd)) {
+ $password = $config->credentialsProvider->passwd;
+ }
+ if (isset($config->credentialsProvider->pass)) {
+ $password = $config->credentialsProvider->pass;
+ }
+ $rc->setCredentials($username, $password);
+ } else {
+ throw new EmailException('Cannot configure credentialsProvider from given config');
+ }
+ } else if (isset($config->credentials)) {
+ $username = NULL;
+ $password = NULL;
+ if (isset($config->credentials->username)) {
+ $username = $config->credentials->username;
+ }
+ if (isset($config->credentials->user)) {
+ $username = $config->credentials->user;
+ }
+ if (isset($config->credentials->password)) {
+ $password = $config->credentials->password;
+ }
+ if (isset($config->credentials->passwd)) {
+ $password = $config->credentials->passwd;
+ }
+ if (isset($config->credentials->pass)) {
+ $password = $config->credentials->pass;
+ }
+ $rc->setCredentials($username, $password);
+ }
+ if (isset($config->secureOption)) {
+ $rc->setSecureOption($config->secureOption);
+ }
+ if (isset($config->charset)) {
+ $rc->setCharset($config->charset);
+ }
+ return $rc;
+ }
+ throw new EmailException('Cannot create SmtpConfig object from given config');
+ }
+
+}
+
diff --git a/src/TgEmail/Email.php b/src/TgEmail/Email.php
new file mode 100644
index 0000000..d641e1a
--- /dev/null
+++ b/src/TgEmail/Email.php
@@ -0,0 +1,236 @@
+sender != NULL) {
+ if (!is_object($this->sender)) {
+ $this->sender = EmailAddress::from($this->sender);
+ }
+ }
+ return $this->sender;
+ }
+
+ public function setSender($email, $name = NULL) {
+ $this->sender = EmailAddress::from($email, $name);
+ return $this;
+ }
+
+ public function getReplyTo() {
+ if ($this->reply_to != NULL) {
+ if (!is_object($this->reply_to)) {
+ $this->reply_to = EmailAddress::from($this->reply_to);
+ }
+ }
+ return $this->reply_to;
+ }
+
+ public function setReplyTo($email, $name = NULL) {
+ $this->reply_to = EmailAddress::from($email, $name);
+ return $this;
+ }
+
+ protected function getRecipients() {
+ if ($this->recipients == NULL) {
+ $this->recipients = new \stdClass;
+ $this->recipients->to = array();
+ $this->recipients->cc = array();
+ $this->recipients->bcc = array();
+ }
+ if (!is_object($this->recipients)) {
+ $this->recipients = json_decode($this->recipients);
+ $this->recipients->to = $this->convertToAddresses($this->recipients->to);
+ $this->recipients->cc = $this->convertToAddresses($this->recipients->cc);
+ $this->recipients->bcc = $this->convertToAddresses($this->recipients->bcc);
+ }
+ return $this->recipients;
+ }
+
+ protected function convertToAddresses($arr) {
+ $rc = array();
+ foreach ($arr AS $address) {
+ $rc[] = EmailAddress::from($address);
+ }
+ return $rc;
+ }
+
+ public function getTo() {
+ return $this->getRecipients()->to;
+ }
+
+ public function addTo($address, $name = NULL) {
+ if (is_array($address)) {
+ foreach ($address AS $a) {
+ $this->addTo($a);
+ }
+ } else if (is_string($address)) {
+ $this->getRecipients()->to[] = EmailAddress::from($address, $name);
+ } else if (is_object($address)) {
+ $this->getRecipients()->to[] = EmailAddress::from($address);
+ } else {
+ throw new EmailException('Cannot add TO recipient(s)');
+ }
+ return $this;
+ }
+
+ public function getCc() {
+ return $this->getRecipients()->cc;
+ }
+
+ public function addCc($address, $name = NULL) {
+ if (is_array($address)) {
+ foreach ($address AS $a) {
+ $this->addCc($a);
+ }
+ } else if (is_string($address)) {
+ $this->getRecipients()->cc[] = EmailAddress::from($address, $name);
+ } else if (is_object($address)) {
+ $this->getRecipients()->cc[] = EmailAddress::from($address);
+ } else {
+ throw new EmailException('Cannot add CC recipient(s)');
+ }
+ return $this;
+ }
+
+ public function getBcc() {
+ return $this->getRecipients()->bcc;
+ }
+
+ public function addBcc($address, $name = NULL) {
+ if (is_array($address)) {
+ foreach ($address AS $a) {
+ $this->addBcc($a);
+ }
+ } else if (is_string($address)) {
+ $this->getRecipients()->bcc[] = EmailAddress::from($address, $name);
+ } else if (is_object($address)) {
+ $this->getRecipients()->bcc[] = EmailAddress::from($address);
+ } else {
+ throw new EmailException('Cannot add BCC recipient(s)');
+ }
+ return $this;
+ }
+
+ public function getSubject() {
+ return $this->subject;
+ }
+
+ public function setSubject($s) {
+ $this->subject = $s;
+ return $this;
+ }
+
+ public function getBody($type = 'text') {
+ if (($this->body != NULL) && is_string($this->body)) {
+ $this->body = json_decode($this->body);
+ } else if ($this->body == NULL) {
+ $this->body = new \stdClass;
+ }
+ if (isset($this->body->$type)) {
+ return $this->body->$type;
+ }
+ return NULL;
+ }
+
+ public function setBody($type = 'text', $body) {
+ if (($this->body != NULL) && is_string($this->body)) {
+ $this->body = json_decode($this->body);
+ } else if ($this->body == NULL) {
+ $this->body = new \stdClass;
+ }
+ $this->body->$type = $body;
+ return $this;
+ }
+
+ public function getAttachments() {
+ if ($this->attachments == NULL) {
+ $this->attachments = array();
+ } else if (is_string($this->attachments)) {
+ $arr = json_decode($this->attachments);
+ $this->attachments = array();
+ foreach ($arr AS $a) {
+ $this->attachments[] = Attachment::from($a);
+ }
+ }
+ return $this->attachments;
+ }
+
+ public function addAttachment(Attachment $a) {
+ $this->getAttachments();
+ $this->attachments[] = $a;
+ return $this;
+ }
+
+ public function addAttachments(array $arr) {
+ $this->getAttachments();
+ foreach ($arr AS $a) {
+ $this->attachments[] = $a;
+ }
+ return $this;
+ }
+
+ public function getSentTime($timezone = 'UTC') {
+ if (($this->sent_time != NULL) && is_string($this->sent_time)) {
+ $this->sent_time = new Date($this->sent_time, $timezone);
+ }
+ return $this->sent_time;
+ }
+
+ public function getQueuedTime($timezone = 'UTC') {
+ if (($this->queued_time != NULL) && is_string($this->queued_time)) {
+ $this->queued_time = new Date($this->queued_time, $timezone);
+ }
+ return $this->queued_time;
+ }
+
+ public function getLogString() {
+ $rc = 'TO='.$this->stringify($this->getRecipients()->to);
+ $rc .= ' CC='.$this->stringify($this->getRecipients()->cc);
+ $rc .= ' BCC='.$this->stringify($this->getRecipients()->bcc);
+ return $rc;
+ }
+
+ public function stringify($addresses) {
+ $rc = array();
+ foreach ($addresses AS $a) {
+ $rc[] = $a->__toString();
+ }
+ return implode(',', $rc);
+ }
+}
+
diff --git a/src/TgEmail/EmailAddress.php b/src/TgEmail/EmailAddress.php
new file mode 100644
index 0000000..113bc2b
--- /dev/null
+++ b/src/TgEmail/EmailAddress.php
@@ -0,0 +1,82 @@
+email = $email;
+ $this->name = $name;
+ }
+
+ /**
+ * Returns the mail-compliant address string.
+ *
+ * @return string the address string.
+ */
+ public function __toString() {
+ if ($this->name != NULL) {
+ return $this->name . ' <' . $this->email . '>';
+ }
+ return '<' . $this->email . '>';
+ }
+
+ /**
+ * Returns a EmailAddress object from a compliant string.
+ *
+ * @param string $s
+ * - a mail compliant string
+ * @return EmailAddress - The EmailAddress object
+ */
+ public static function from($s, $name = NULL) {
+ if (is_string($s)) {
+ if ($name == NULL) {
+ $pos = strpos($s, '<');
+ if ($pos !== FALSE) {
+ $name = $pos > 0 ? trim(substr($s, 0, $pos)) : NULL;
+ if ($name == '') $name = NULL;
+
+ $email = substr($s, $pos + 1);
+ $pos = strpos($email, '>');
+ if ($pos !== FALSE) {
+ $email = trim(substr($email, 0, $pos));
+ }
+
+ return new EmailAddress($email, $name);
+ }
+ return new EmailAddress($s);
+ } else {
+ return new EmailAddress($s, $name);
+ }
+ } else if (is_a($s, 'TgEmail\\EmailAddress')) {
+ return $s;
+ } else if (is_object($s)) {
+ return new EmailAddress($s->email, $s->name);
+ }
+ }
+}
+
diff --git a/src/TgEmail/EmailConfig.php b/src/TgEmail/EmailConfig.php
new file mode 100644
index 0000000..24dc5c6
--- /dev/null
+++ b/src/TgEmail/EmailConfig.php
@@ -0,0 +1,183 @@
+timezone = 'UTC';
+ $this->mailMode = EmailQueue::DEFAULT;
+ $this->setSmtpConfig($smtpConfig);
+ $this->setRerouteConfig($rerouteConfig);
+ $this->setBccConfig($bccConfig);
+ $this->debugAddress = array();
+ $this->defaultSender = NULL;
+ $this->subjectPrefix = NULL;
+ }
+
+ public function getTimezone() {
+ return $this->timezone;
+ }
+
+ public function setTimezone($tz) {
+ $this->timezone = $tz;
+ return $this;
+ }
+
+ public function getMailMode() {
+ return $this->mailMode;
+ }
+
+ public function setMailMode($mailMode, $config = NULL) {
+ if ($mailMode == EmailQueue::REROUTE) {
+ if ($config != NULL) {
+ $this->setRerouteConfig($config);
+ }
+ if ($this->getRerouteConfig() == NULL) {
+ throw new EmailException('No RerouteConfig available. Set the config along with the mailMode.');
+ }
+ } else if ($mailMode == EmailQueue::BCC) {
+ if ($config != NULL) {
+ $this->setBccConfig($config);
+ }
+ if ($this->getBccConfig() == NULL) {
+ throw new EmailException('No BccConfig available. Set the config along with the mailMode.');
+ }
+ }
+ $this->mailMode = $mailMode;
+ return $this;
+ }
+
+ public function getSmtpConfig() {
+ return $this->smtpConfig;
+ }
+
+ public function setSmtpConfig($config) {
+ if (($config == NULL) || is_a($config, 'TgEmail\\Config\\SmtpConfig')) {
+ $this->smtpConfig = $config;
+ return $this;
+ }
+ throw new EmailException('Not a SmtpConfig object.');
+ }
+
+ public function getRerouteConfig() {
+ return $this->rerouteConfig;
+ }
+
+ public function setRerouteConfig($config) {
+ if (($config == NULL) || is_a($config, 'TgEmail\\Config\\RerouteConfig')) {
+ $this->rerouteConfig = $config;
+ return $this;
+ }
+ throw new EmailException('Not a RerouteConfig object.');
+ }
+
+ public function getBccConfig() {
+ return $this->bccConfig;
+ }
+
+ public function setBccConfig($config) {
+ if (($config == NULL) || is_a($config, 'TgEmail\\Config\\BccConfig')) {
+ $this->bccConfig = $config;
+ return $this;
+ }
+ throw new EmailException('Not a BccConfig object.');
+ }
+
+ public function getDefaultSender() {
+ return $this->defaultSender;
+ }
+
+ public function setDefaultSender($email, $name = NULL) {
+ $this->defaultSender = EmailAddress::from($email, $name);
+ return $this;
+ }
+
+ public function getDebugAddress() {
+ return $this->debugAddress;
+ }
+
+ public function addDebugAddress($address, $name = NULL) {
+ if (is_array($address)) {
+ foreach ($address AS $a) {
+ $this->addDebugAddress($a);
+ }
+ } else if (is_string($address)) {
+ $this->debugAddress[] = EmailAddress::from($address, $name);
+ } else if (is_object($address)) {
+ $this->debugAddress[] = EmailAddress::from($address);
+ } else {
+ throw new EmailException('Cannot add debugging recipient(s)');
+ }
+ return $this;
+ }
+
+ public function getSubjectPrefix() {
+ if ($this->subjectPrefix == NULL) return '';
+ return $this->subjectPrefix;
+ }
+
+ public function setSubjectPrefix($s) {
+ $this->subjectPrefix = $s;
+ }
+
+ public static function from($config) {
+ if (is_array($config)) {
+ $config = json_decode(json_encode($config));
+ } else if (is_string($config)) {
+ $config = json_decode($config);
+ }
+ if (is_object($config)) {
+ $rc = new EmailConfig();
+ if (isset($config->timezone)) {
+ $rc->setTimezone($config->timezone);
+ }
+ if (isset($config->smtpConfig)) {
+ $rc->setSmtpConfig(SmtpConfig::from($config->smtpConfig));
+ }
+ if (isset($config->rerouteConfig)) {
+ $rc->setRerouteConfig(RerouteConfig::from($config->rerouteConfig));
+ }
+ if (isset($config->bccConfig)) {
+ $rc->setBccConfig(BccConfig::from($config->bccConfig));
+ }
+ if (isset($config->mailMode)) {
+ $rc->setMailMode($config->mailMode);
+ }
+ if (isset($config->debugAddress)) {
+ $rc->addDebugAddress($config->debugAddress);
+ }
+ if (isset($config->defaultSender)) {
+ $rc->setDefaultSender($config->defaultSender);
+ }
+ if (isset($config->subjectPrefix)) {
+ $rc->setSubjectPrefix($config->subjectPrefix);
+ }
+ return $rc;
+ }
+ throw new EmailException('Cannot create EmailConfig object from given config');
+ }
+
+}
+
diff --git a/src/TgEmail/EmailException.php b/src/TgEmail/EmailException.php
new file mode 100644
index 0000000..6d4062e
--- /dev/null
+++ b/src/TgEmail/EmailException.php
@@ -0,0 +1,22 @@
+config = $config;
+ $this->mailDAO = $mailDAO;
+ $this->mailer = NULL;
+ }
+
+ public function createTestMail() {
+ $rc = new Email();
+ $rc->setSender($this->config->getDefaultSender());
+ $rc->setBody(Email::TEXT, 'This is a successfull e-mail test (TXT)');
+ $rc->setBody(Email::HTML, 'Success
This is a successfull e-mail test (HTML)
');
+ $rc->addTo($this->config->getDebugAddress());
+ $rc->setSubject($this->config->getSubjectPrefix() . 'Test-Mail');
+ return $rc;
+ }
+
+ /**
+ * Sends a test-mail to private account
+ */
+ public function sendTestMail() {
+ $email = $this->createTestMail();
+ return $this->_send($email);
+ }
+
+ /**
+ * Set a new mail mode.
+ * @param string $mailMode - the new mail mode
+ * @param object $config - the configuration of this mail mode (optional when config already available or not required)
+ */
+ public function setMailMode($mailMode, $config = NULL) {
+ $this->config->setMailMode($mailMode, $config);
+ }
+
+ /**
+ * TODO: smth like queue($email, $recipients) ?
+ * Sends multiple emails.
+ *
+ * @param
+ * array of
+ * mixed recipients - array of recipients or single recipient to send to
+ * string templateName - mail template name to be used, located in /site/email//.[html|txt].php
+ * string subject - subject
+ * mixed params - parameters to be given to email template
+ * string domain - the domain this mail belongs to
+ * @return array of
+ * boolean success - overall success
+ * array errors - individual boolean return codes for each mail
+ *
+ public function queueMails($mailInfos) {
+ $rc = array(
+ 'success' => true,
+ 'errors' => array(),
+ );
+ foreach ($mailInfos as $mail) {
+ $c = $this->queueMail($mail['recipients'], $mail['templateName'], $mail['subject'], $mail['params']);
+ $rc['error'][] = $c;
+ if (! $c) $rc['success'] = false;
+ }
+ return $rc;
+ }
+ */
+
+ protected function getMailer() {
+ if ($this->mailer == null) {
+ $this->mailer = new PHPMailer();
+ $this->mailer->IsSMTP(); // telling the class to use SMTP
+ $this->mailer->SMTPDebug = $this->config->getSmtpConfig()->getDebugLevel();
+ $this->mailer->SMTPAuth = $this->config->getSmtpConfig()->isAuth();
+ $this->mailer->SMTPSecure = $this->config->getSmtpConfig()->getSecureOption();
+ $this->mailer->Port = $this->config->getSmtpConfig()->getPort();
+ $this->mailer->Host = $this->config->getSmtpConfig()->getHost();
+ $this->mailer->Username = $this->config->getSmtpConfig()->getUsername();
+ $this->mailer->Password = $this->config->getSmtpConfig()->getPassword();
+ $this->mailer->CharSet = $this->config->getSmtpConfig()->getCharset();
+ $this->mailer->Encoding = 'base64';
+ } else {
+ $this->mailer->clearAllRecipients();
+ $this->mailer->clearAttachments();
+ $this->mailer->clearCustomHeaders();
+ $this->mailer->clearReplyTos();
+ }
+ return $this->mailer;
+ }
+
+ /**
+ * Synchronously send emails from queue according to priority.
+ */
+ public function processQueue($maxTime = 0) {
+ if ($maxTime <= 0) $maxTime = 60;
+
+ if ($this->mailDAO != NULL) {
+ // Make sure the request object was created
+ Request::getRequest();
+
+ // Return statistics
+ $rc = new \stdClass();
+ $rc->pending = 0;
+ $rc->skipped = 0;
+ $rc->processed = 0;
+ $rc->sent = 0;
+ $rc->failed = 0;
+
+ // do housekeeping
+ $this->mailDAO->housekeeping();
+
+ // Retrieve pending emails
+ $emails = $this->mailDAO->getPendingEmails();
+ $rc->pending = count($emails);
+ foreach ($emails as $email) {
+ // send
+ if ($this->sendByUid($email->uid, TRUE)) {
+ $rc->sent++;
+ } else {
+ $rc->failed++;
+ }
+ $rc->processed++;
+ if (Request::getRequest()->getElapsedTime() > $maxTime) break;
+ }
+ return $rc;
+ }
+ throw new EmailException('QueueProcessing not supported. No DAO available.');
+ }
+
+ /**
+ * Synchronously send email from queue with id.
+ */
+ public function sendByUid($uid, $checkStatus = FALSE) {
+ if ($this->mailDAO != NULL) {
+ // Retrieve
+ $email = $this->mailDAO->get($uid);
+
+ if ($email != NULL) {
+ // Mark as being processed
+ $email->status = Email::PROCESSING;
+ $this->mailDAO->save($email);
+
+ // send
+ $rc = $this->_send($email);
+
+ // Save
+ $email->status = Email::SENT;
+ if (!$rc) {
+ $email->failed_attempts ++;
+ if ($email->failed_attempts >= 3) {
+ $email->status = Email::FAILED;
+ foreach ($email->getAttachments() AS $a) {
+ if ($a->deleteAfterSent && $a->deleteAfterFailed) {
+ unlink($a->path);
+ }
+ }
+ } else {
+ $email->status = Email::PENDING;
+ }
+ } else {
+ $email->sent_time = new Date(time(), $this->config->getTimezone());
+ }
+ $this->mailDAO->save($email);
+ return $rc;
+ }
+ return FALSE;
+ }
+ throw new EmailException('No DAO available. Cannot retrieve e-mail by ID.');
+ }
+
+ /**
+ * Creates a new Email object that reflects the MailMode settings.
+ */
+ public function getReconfiguredEmail(Email $email) {
+ $rc = new Email();
+
+ if ($email->getSender() != NULL) {
+ $rc->setSender($email->getSender());
+ } else {
+ $rc->setSender($this->config->getDefaultSender());
+ }
+ $rc->setReplyTo($email->getReplyTo());
+ $rc->addAttachments($email->getAttachments());
+ $rc->setBody(Email::TEXT, $email->getBody(Email::TEXT));
+ $rc->setBody(Email::HTML, $email->getBody(Email::HTML));
+
+ if ($this->config->getMailMode() == EmailQueue::REROUTE) {
+ $rc->setSubject($this->config->getRerouteConfig()->getSubjectPrefix().$this->config->getSubjectPrefix().$email->getSubject().' - '.$email->stringify($email->getTo()));
+ $rc->addTo($this->config->getRerouteConfig()->getRecipients());
+ } else {
+ $rc->setSubject($this->config->getSubjectPrefix().$email->getSubject());
+ $rc->addTo($email->getTo());
+ $rc->addCc($email->getCc());
+ $rc->addBcc($email->getBcc());
+ if ($this->config->getMailMode() == EmailQueue::BCC) {
+ $rc->addBcc($this->config->getBccConfig()->getRecipients());
+ }
+ }
+ return $rc;
+ }
+
+ public function send(Email $email) {
+ // Modify mail according to sending mode
+ $email = $this->getReconfiguredEmail($email);
+ return $this->_send($email);
+ }
+
+ /**
+ * Synchronously send email object.
+ */
+ protected function _send(Email $email) {
+ // Start
+ $phpMailer = $this->getMailer();
+
+ // Sender
+ $phpMailer->setFrom($email->getSender()->email, $email->getSender()->name);
+
+ // Reply-To
+ if ($email->getReplyTo() != NULL) {
+ $phpMailer->addReplyTo($email->getReplyTo()->email, $email->getReplyTo()->name);
+ }
+
+ // Recipients
+ foreach ($email->getTo() as $recipient) {
+ $phpMailer->addAddress($recipient->email, $recipient->name);
+ }
+ foreach ($email->getCc() as $recipient) {
+ $phpMailer->addCC($recipient->email, $recipient->name);
+ }
+ foreach ($email->getBcc() as $recipient) {
+ $phpMailer->addBCC($recipient->email, $recipient->name);
+ }
+
+ // Subject
+ $phpMailer->Subject = '=?utf-8?B?' . base64_encode($email->getSubject()) . '?=';
+
+ // Body
+ if ($email->getBody(Email::HTML) != NULL) {
+ $phpMailer->isHTML(true);
+ $phpMailer->Body = $email->getBody(Email::HTML);
+ if ($email->getBody(Email::TEXT) != NULL) {
+ $phpMailer->AltBody = $email->getBody(Email::TEXT);
+ }
+ } else {
+ $phpMailer->Body = $email->getBody(Email::TEXT);
+ }
+
+ // Attachments
+ foreach ($email->getAttachments() as $a) {
+ if ($a->type == Attachment::ATTACHED) {
+ $phpMailer->AddAttachment($a->path, $a->name, 'base64', $a->mimeType);
+ } else if ($a->type == 'embedded') {
+ $phpMailer->AddEmbeddedImage($a->path, $a->cid, $a->name);
+ }
+ }
+
+ $rc = TRUE;
+ if ($this->config->getMailMode() != EmailQueue::BLOCK) {
+ $rc = $phpMailer->send();
+ Log::debug('Mail sent: '.$email->getLogString());
+ if (!$rc) {
+ Log::error("Mailer Error: " . $phpMailer->ErrorInfo);
+ } else {
+ foreach ($email->getAttachments() as $a) {
+ if ($a->deleteAfterSent) {
+ unlink($a->path);
+ }
+ }
+ }
+ }
+ return $rc;
+ }
+
+ public function queue(Email $email) {
+ // Modify mail according to sending mode
+ $email = $this->getReconfiguredEmail($email);
+ return $this->_queue($email);
+ }
+
+ /**
+ * Queues an email.
+ *
+ * @param Email $email
+ * - \WebApp\Email object
+ * @return true when e-mail was queued
+ */
+ protected function _queue($email) {
+ if ($this->mailDAO != NULL) {
+ if ($this->config->getMailMode() != EmailQueue::BLOCK) {
+ $email->queued_time = new Date(time(), $this->config->getTimezone());
+ $email->status = Email::PENDING;
+ $email->failed_attempts = 0;
+ $email->sent_time = NULL;
+ $rc = $this->mailDAO->create($email);
+ return is_int($rc);
+ }
+ return TRUE;
+ }
+ throw new EmailException('Queueing is not supported. No DAO available.');
+ }
+
+}
+
diff --git a/src/TgEmail/EmailsDAO.php b/src/TgEmail/EmailsDAO.php
new file mode 100644
index 0000000..f4adb9d
--- /dev/null
+++ b/src/TgEmail/EmailsDAO.php
@@ -0,0 +1,58 @@
+checkTable();
+ }
+
+ public function checkTable() {
+ $res = $this->database->query('SELECT * FROM '.$this->tableName);
+ if ($res === FALSE) {
+ // Create it (try)
+ $sql =
+ 'CREATE TABLE `'.$this->tableName.'` ( '.
+ '`'.$this->idColumn.'` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT \'ID of queue element\', '.
+ '`sender` VARCHAR(200) NOT NULL COMMENT \'sender address\', '.
+ '`reply_to` VARCHAR(200) NULL COMMENT \'Reply-To address\', '.
+ '`recipients` TEXT COLLATE utf8mb4_bin NOT NULL COMMENT \'email recipients\', '.
+ '`subject` VARCHAR(200) NOT NULL COMMENT \'email subject\', '.
+ '`body` TEXT COLLATE utf8mb4_bin NOT NULL COMMENT \'email bodies\', '.
+ '`attachments` TEXT COLLATE utf8mb4_bin NOT NULL COMMENT \'attachment data\', '.
+ '`queued_time` DATETIME NOT NULL COMMENT \'Time the email was queued\', '.
+ '`status` VARCHAR(20) NOT NULL COMMENT \'email subject\', '.
+ '`sent_time` DATETIME NULL COMMENT \'Time the email was sent successfully\', '.
+ '`failed_attempts` INT(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT \'Number of failed sending attempts\', '.
+ 'PRIMARY KEY (`'.$this->idColumn.'`) '.
+ ') ENGINE = InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT = \'Email Queue\'';
+
+ $res = $this->database->query($sql);
+ if ($res === FALSE) {
+ throw new EmailException('Cannot create table '.$this->tableName.': '.$this->database->error());
+ }
+ }
+
+ }
+
+ public function housekeeping($maxSentDays = 90, $maxFailedDays = 180) {
+ $this->database->delete($this->tableName, 'status=\'sent\' AND TIMESTAMPDIFF(DAY, sent_time, NOW()) >= '.$maxSentDays);
+ $this->database->delete($this->tableName, 'status=\'failed\' AND TIMESTAMPDIFF(DAY, sent_time, NOW()) >= '.$maxFailedDays);
+ }
+
+ public function getPendingEmails() {
+ return $this->find(array('status' => Email::PENDING), array('queued_time'));
+ }
+}
+
diff --git a/tests/TgEmail/Config/BccConfigTest.php b/tests/TgEmail/Config/BccConfigTest.php
new file mode 100644
index 0000000..a2d009d
--- /dev/null
+++ b/tests/TgEmail/Config/BccConfigTest.php
@@ -0,0 +1,90 @@
+addRecipients('John Doe getRecipients();
+ $this->assertEquals(1, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ }
+
+ public function testAddRecipientsWithObject(): void {
+ $config = new BccConfig();
+ $config->addRecipients(EmailAddress::from('John Doe getRecipients();
+ $this->assertEquals(1, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ }
+
+ public function testAddRecipientsWithArray(): void {
+ $config = new BccConfig();
+ $config->addRecipients(array(
+ EmailAddress::from('John Doe getRecipients();
+ $this->assertEquals(2, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ $this->assertEquals('Jane Doe ', $recipients[1]->__toString());
+ }
+
+ public function testFromWithArray(): void {
+ $origConfig = array(
+ 'recipients' => array(
+ 'John Doe 'Jane Doe',
+ 'email' => 'jane.doe@example.com',
+ ),
+ ),
+ );
+
+ $config = BccConfig::from($origConfig);
+ $recipients = $config->getRecipients();
+ $this->assertEquals(2, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ $this->assertEquals('Jane Doe ', $recipients[1]->__toString());
+ }
+
+ public function testFromWithString(): void {
+ $origConfig = self::getJsonTestString();
+
+ $config = BccConfig::from($origConfig);
+ $recipients = $config->getRecipients();
+ $this->assertEquals(2, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ $this->assertEquals('Jane Doe ', $recipients[1]->__toString());
+ }
+
+ public function testFromWithObject(): void {
+ $origConfig = json_decode(self::getJsonTestString());
+
+ $config = BccConfig::from($origConfig);
+ $recipients = $config->getRecipients();
+ $this->assertEquals(2, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ $this->assertEquals('Jane Doe ', $recipients[1]->__toString());
+ }
+
+ public static function getJsonTestString() {
+ return '{"recipients":["John Doe addRecipients('John Doe getRecipients();
+ $this->assertEquals(1, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ }
+
+ public function testAddRecipientsWithObject(): void {
+ $config = new RerouteConfig();
+ $config->addRecipients(EmailAddress::from('John Doe getRecipients();
+ $this->assertEquals(1, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ }
+
+ public function testAddRecipientsWithArray(): void {
+ $config = new RerouteConfig();
+ $config->addRecipients(array(
+ EmailAddress::from('John Doe getRecipients();
+ $this->assertEquals(2, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ $this->assertEquals('Jane Doe ', $recipients[1]->__toString());
+ }
+
+ public function testSetSubjectPrefix(): void {
+ $config = new RerouteConfig();
+ $config->setSubjectPrefix('A specific prefix');
+ $this->assertEquals('A specific prefix', $config->getSubjectPrefix());
+ }
+
+ public function testFromWithArray(): void {
+ $origConfig = array(
+ 'recipients' => array(
+ 'John Doe 'Jane Doe',
+ 'email' => 'jane.doe@example.com',
+ ),
+ ),
+ 'subjectPrefix' => 'A specific prefix',
+ );
+
+ $config = RerouteConfig::from($origConfig);
+ $recipients = $config->getRecipients();
+ $this->assertEquals(2, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ $this->assertEquals('Jane Doe ', $recipients[1]->__toString());
+ $this->assertEquals('A specific prefix', $config->getSubjectPrefix());
+ }
+
+ public function testFromWithString(): void {
+ $origConfig = self::getJsonTestString();
+
+ $config = RerouteConfig::from($origConfig);
+ $recipients = $config->getRecipients();
+ $this->assertEquals(2, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ $this->assertEquals('Jane Doe ', $recipients[1]->__toString());
+ $this->assertEquals('A specific prefix', $config->getSubjectPrefix());
+ }
+
+ public function testFromWithObject(): void {
+ $origConfig = json_decode(self::getJsonTestString());
+
+ $config = RerouteConfig::from($origConfig);
+ $recipients = $config->getRecipients();
+ $this->assertEquals(2, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ $this->assertEquals('Jane Doe ', $recipients[1]->__toString());
+ $this->assertEquals('A specific prefix', $config->getSubjectPrefix());
+ }
+
+ public static function getJsonTestString() {
+ return '{"recipients":["John Doe setHost('www.example.com');
+ $this->assertEquals('www.example.com', $config->getHost());
+ }
+
+ public function testSetPort(): void {
+ $config = new SmtpConfig();
+ $config->setPort(587);
+ $this->assertEquals(587, $config->getPort());
+ }
+
+ public function testSetDebugLevel(): void {
+ $config = new SmtpConfig();
+ $config->setDebuglevel(SMTP::DEBUG_SERVER);
+ $this->assertEquals(SMTP::DEBUG_SERVER, $config->getDebuglevel());
+ }
+
+
+ public function testSetAuth(): void {
+ $config = new SmtpConfig();
+ $config->setAuth(TRUE);
+ $this->assertTrue($config->isAuth());
+ }
+
+
+ public function testSetCredentials(): void {
+ $config = new SmtpConfig();
+ $config->setCredentials('username', 'password');
+ $this->assertEquals('username', $config->getUsername());
+ $this->assertEquals('password', $config->getPassword());
+ }
+
+
+ public function testSetSecureOption(): void {
+ $config = new SmtpConfig();
+ $config->setSecureOption(PHPMailer::ENCRYPTION_STARTTLS);
+ $this->assertEquals(PHPMailer::ENCRYPTION_STARTTLS, $config->getSecureOption());
+ }
+
+
+ public function testSetCharset(): void {
+ $config = new SmtpConfig();
+ $config->setCharset('utf8');
+ $this->assertEquals('utf8', $config->getCharset());
+ }
+
+ public function testFromWithArray(): void {
+ $origConfig = array(
+ 'host' => 'www.example.com',
+ 'port' => 587,
+ 'debugLevel' => SMTP::DEBUG_SERVER,
+ 'auth' => TRUE,
+ 'credentials' => array(
+ 'user' => 'username',
+ 'pass' => 'password',
+ ),
+ 'secureOption' => PHPMailer::ENCRYPTION_STARTTLS,
+ 'charset' => 'utf8',
+ );
+
+ $config = SmtpConfig::from($origConfig);
+ $this->assertEquals('www.example.com', $config->getHost());
+ $this->assertEquals(587, $config->getPort());
+ $this->assertEquals(SMTP::DEBUG_SERVER, $config->getDebuglevel());
+ $this->assertTrue($config->isAuth());
+ $this->assertEquals('username', $config->getUsername());
+ $this->assertEquals('password', $config->getPassword());
+ $this->assertEquals(PHPMailer::ENCRYPTION_STARTTLS, $config->getSecureOption());
+ $this->assertEquals('utf8', $config->getCharset());
+ }
+
+ public function testFromWithString(): void {
+ $origConfig = self::getJsonTestString();
+
+ $config = SmtpConfig::from($origConfig);
+ $this->assertEquals('www.example.com', $config->getHost());
+ $this->assertEquals(587, $config->getPort());
+ $this->assertEquals(SMTP::DEBUG_SERVER, $config->getDebuglevel());
+ $this->assertTrue($config->isAuth());
+ $this->assertEquals('username', $config->getUsername());
+ $this->assertEquals('password', $config->getPassword());
+ $this->assertEquals(PHPMailer::ENCRYPTION_STARTTLS, $config->getSecureOption());
+ $this->assertEquals('utf8', $config->getCharset());
+ }
+
+ public function testFromWithObject(): void {
+ $origConfig = json_decode(self::getJsonTestString());
+
+ $config = SmtpConfig::from($origConfig);
+ $this->assertEquals('www.example.com', $config->getHost());
+ $this->assertEquals(587, $config->getPort());
+ $this->assertEquals(SMTP::DEBUG_SERVER, $config->getDebuglevel());
+ $this->assertTrue($config->isAuth());
+ $this->assertEquals('username', $config->getUsername());
+ $this->assertEquals('password', $config->getPassword());
+ $this->assertEquals(PHPMailer::ENCRYPTION_STARTTLS, $config->getSecureOption());
+ $this->assertEquals('utf8', $config->getCharset());
+ }
+
+ public static function getJsonTestString() {
+ return '{"host":"www.example.com","port":587,"debugLevel":2,"auth":true,"credentials":{"user":"username","pass":"password"},"secureOption":"tls","charset":"utf8"}';
+ }
+}
+
diff --git a/tests/TgEmail/EmailAddressTest.php b/tests/TgEmail/EmailAddressTest.php
new file mode 100644
index 0000000..5be8b1a
--- /dev/null
+++ b/tests/TgEmail/EmailAddressTest.php
@@ -0,0 +1,59 @@
+assertEquals('', $addr->__toString());
+ }
+
+ public function testToStringWithEmailName(): void {
+ $addr = new EmailAddress('john.doe@example.com', 'John Doe');
+ $this->assertEquals('John Doe ', $addr->__toString());
+ }
+
+ public function testFromWithEmail1(): void {
+ $addr = EmailAddress::from('john.doe@example.com');
+ $this->assertEquals('', $addr->__toString());
+ }
+
+ public function testFromWithEmail2(): void {
+ $addr = EmailAddress::from('');
+ $this->assertEquals('', $addr->__toString());
+ }
+
+ public function testFromWithString(): void {
+ $addr = EmailAddress::from('John Doe ');
+ $this->assertEquals('John Doe ', $addr->__toString());
+ }
+
+ public function testFromWithEmailName(): void {
+ $addr = EmailAddress::from('john.doe@example.com', 'John Doe');
+ $this->assertEquals('John Doe ', $addr->__toString());
+ }
+
+ public function testFromWithObject(): void {
+ $obj = new \stdClass;
+ $obj->name = 'John Doe';
+ $obj->email = 'john.doe@example.com';
+ $addr = EmailAddress::from($obj);
+ $this->assertEquals('John Doe ', $addr->__toString());
+ }
+
+ public function testFromWithAddress(): void {
+ $obj = new EmailAddress('john.doe@example.com', 'John Doe');
+ $addr = EmailAddress::from($obj);
+ $this->assertEquals('John Doe ', $addr->__toString());
+ }
+}
+
diff --git a/tests/TgEmail/EmailConfigTest.php b/tests/TgEmail/EmailConfigTest.php
new file mode 100644
index 0000000..1cfab09
--- /dev/null
+++ b/tests/TgEmail/EmailConfigTest.php
@@ -0,0 +1,158 @@
+setTimezone('Europe/Berlin');
+ $this->assertEquals('Europe/Berlin', $config->getTimezone());
+ }
+
+ public function testSetMailMode(): void {
+ $config = new EmailConfig();
+ $config->setMailMode(EmailQueue::BLOCK);
+ $this->assertEquals(EmailQueue::BLOCK, $config->getMailMode());
+ }
+
+ public function testSetSmtpConfig(): void {
+ $config = new EmailConfig();
+ $smtpConfig = SmtpConfig::from(SmtpConfigTest::getJsonTestString());
+ $config->setSmtpConfig($smtpConfig);
+ $this->assertEquals($smtpConfig, $config->getSmtpConfig());
+ }
+
+
+ public function testSetRerouteConfig(): void {
+ $config = new EmailConfig();
+ $rerouteConfig = RerouteConfig::from(RerouteConfigTest::getJsonTestString());
+ $config->setRerouteConfig($rerouteConfig);
+ $this->assertEquals($rerouteConfig, $config->getRerouteConfig());
+ }
+
+ public function testSetBccConfig(): void {
+ $config = new EmailConfig();
+ $bccConfig = BccConfig::from(BccConfigTest::getJsonTestString());
+ $config->setBccConfig($bccConfig);
+ $this->assertEquals($bccConfig, $config->getBccConfig());
+ }
+
+ public function testAddDebugAddressWithString(): void {
+ $config = new EmailConfig();
+ $config->addDebugAddress('John Doe getDebugAddress();
+ $this->assertEquals(1, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ }
+
+ public function testAddDebugAddressWithObject(): void {
+ $config = new EmailConfig();
+ $config->addDebugAddress(EmailAddress::from('John Doe getDebugAddress();
+ $this->assertEquals(1, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ }
+
+ public function testAddDebugAddressWithArray(): void {
+ $config = new EmailConfig();
+ $config->addDebugAddress(array(
+ EmailAddress::from('John Doe getDebugAddress();
+ $this->assertEquals(2, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ $this->assertEquals('Jane Doe ', $recipients[1]->__toString());
+ }
+
+ public function testSetDefaultSender(): void {
+ $config = new EmailConfig();
+ $config->setDefaultSender(EmailAddress::from('John Doe '));
+ $this->assertEquals('John Doe ', $config->getDefaultSender()->__toString());
+ }
+
+ public function testSetSubjectPrefix(): void {
+ $config = new EmailConfig();
+ $config->setSubjectPrefix('A subject prefix');
+ $this->assertEquals('A subject prefix', $config->getSubjectPrefix());
+ }
+
+
+ public function testFromWithArray(): void {
+ $origConfig = array(
+ 'timezone' => 'Europe/Berlin',
+ 'mailMode' => EmailQueue::BLOCK,
+ 'smtpConfig' => json_decode(SmtpConfigTest::getJsonTestString(), TRUE),
+ 'rerouteConfig' => json_decode(RerouteConfigTest::getJsonTestString(), TRUE),
+ 'bccConfig' => json_decode(BccConfigTest::getJsonTestString(), TRUE),
+ 'debugAddress' => 'Jane Doe 'John Doe 'A subject prefix',
+ );
+
+ $config = EmailConfig::from($origConfig);
+ $this->assertEquals('Europe/Berlin', $config->getTimezone());
+ $this->assertEquals(EmailQueue::BLOCK, $config->getMailMode());
+ $this->assertInstanceOf(SmtpConfig::class, $config->getSmtpConfig());
+ $this->assertInstanceOf(RerouteConfig::class, $config->getRerouteConfig());
+ $this->assertInstanceOf(BccConfig::class, $config->getBccConfig());
+ $this->assertEquals('Jane Doe ', $config->getDebugAddress()[0]->__toString());
+ $this->assertEquals('John Doe ', $config->getDefaultSender()->__toString());
+ $this->assertEquals('A subject prefix', $config->getSubjectPrefix());
+ }
+
+ public function testFromWithString(): void {
+ $origConfig = self::getJsonTestString();
+
+ $config = EmailConfig::from($origConfig);
+ $this->assertEquals('Europe/Berlin', $config->getTimezone());
+ $this->assertEquals(EmailQueue::BLOCK, $config->getMailMode());
+ $this->assertInstanceOf(SmtpConfig::class, $config->getSmtpConfig());
+ $this->assertInstanceOf(RerouteConfig::class, $config->getRerouteConfig());
+ $this->assertInstanceOf(BccConfig::class, $config->getBccConfig());
+ $this->assertEquals('Jane Doe ', $config->getDebugAddress()[0]->__toString());
+ $this->assertEquals('John Doe ', $config->getDefaultSender()->__toString());
+ $this->assertEquals('A subject prefix', $config->getSubjectPrefix());
+ }
+
+ public function testFromWithObject(): void {
+ $origConfig = json_decode(self::getJsonTestString());
+
+ $config = EmailConfig::from($origConfig);
+ $this->assertEquals('Europe/Berlin', $config->getTimezone());
+ $this->assertEquals(EmailQueue::BLOCK, $config->getMailMode());
+ $this->assertInstanceOf(SmtpConfig::class, $config->getSmtpConfig());
+ $this->assertInstanceOf(RerouteConfig::class, $config->getRerouteConfig());
+ $this->assertInstanceOf(BccConfig::class, $config->getBccConfig());
+ $this->assertEquals('Jane Doe ', $config->getDebugAddress()[0]->__toString());
+ $this->assertEquals('John Doe ', $config->getDefaultSender()->__toString());
+ $this->assertEquals('A subject prefix', $config->getSubjectPrefix());
+ }
+
+ public static function getJsonTestString() {
+ return '{"timezone":"Europe\/Berlin","mailMode":"block","smtpConfig":{"host":"www.example.com","port":587,"debugLevel":2,"auth":true,"credentials":{"user":"username","pass":"password"},"secureOption":"tls","charset":"utf8"},"rerouteConfig":{"recipients":["John Doe This class requires enviroment variable EMAIL_DATABASE and EMAIL_TEST_SMTP
+ * to contain the configuration for the database access and SMTP parameters
+ * to successfully test the sending and queuing.
+ * @author ralph
+ *
+ */
+class EmailQueueTest extends TestCase {
+
+ private static $database = NULL;
+ private static $dao = NULL;
+ private static $queue = NULL;
+ private static $queueConfig = NULL;
+
+ public function testSendWithBlocked(): void {
+ if (getenv('EMAIL_TEST_SMTP') != NULL) {
+ $config = json_decode(getenv('EMAIL_TEST_SMTP'));
+ $queue = self::getEmailQueue(EmailQueue::BLOCK);
+ $email = new Email();
+ $email->setSubject('[EmailQueueTest] testSendWithBlocked');
+ $email->setBody(Email::HTML, 'EmailQueueTest::testSendWithBlocked
This email shall not have been delivered! Test failed.
');
+ $email->setBody(Email::TEXT, "EmailQueueTest::testSendWithBlocked\n=================\n\nThis email shall not have been delivered! Test failed.\n");
+ $email->addTo(EmailAddress::from($config->targetAddress));
+ if (isset($config->replyToAddress)) $email->setReplyTo(EmailAddress::from($config->replyToAddress));
+
+ $this->assertTrue($queue->send($email));
+ } else {
+ // Just to not create a test warning
+ $this->assertTrue(TRUE);
+ }
+ }
+
+ public function testSendWithReroute(): void {
+ if (getenv('EMAIL_TEST_SMTP') != NULL) {
+ $config = json_decode(getenv('EMAIL_TEST_SMTP'));
+ $queue = self::getEmailQueue(EmailQueue::REROUTE);
+ $email = new Email();
+ $email->setSubject('testSendWithReroute');
+ $email->setBody(Email::HTML, 'EmailQueueTest::testSendWithReroute
This email shall have arrived at your reroute mailbox: '.self::$queueConfig->getRerouteConfig()->getRecipients()[0]->email.'
');
+ $email->setBody(Email::TEXT, "EmailQueueTest::testSendWithReroute\n=================\n\nThis email shall have arrived at your reroute mailbox: ".self::$queueConfig->getRerouteConfig()->getRecipients()[0]->email."\n");
+ $email->addTo(EmailAddress::from($config->targetAddress));
+ if (isset($config->replyToAddress)) $email->setReplyTo(EmailAddress::from($config->replyToAddress));
+
+ $this->assertTrue($queue->send($email));
+ } else {
+ // Just to not create a test warning
+ $this->assertTrue(TRUE);
+ }
+ }
+
+ public function testSendWithBcc(): void {
+ if (getenv('EMAIL_TEST_SMTP') != NULL) {
+ $config = json_decode(getenv('EMAIL_TEST_SMTP'));
+ $queue = self::getEmailQueue(EmailQueue::BCC);
+ $email = new Email();
+ $email->setSubject('testSendWithBcc');
+ $email->setBody(Email::HTML, 'EmailQueueTest::testSendWithBcc
This email shall have arrived at your BCC mailbox: '.self::$queueConfig->getBccConfig()->getRecipients()[0]->email.'
');
+ $email->setBody(Email::TEXT, "EmailQueueTest::testSendWithBcc\n=================\n\nThis email shall have arrived at your target mailbox: ".self::$queueConfig->getBccConfig()->getRecipients()[0]->email."\n");
+ $email->addTo(EmailAddress::from($config->targetAddress));
+ if (isset($config->replyToAddress)) $email->setReplyTo(EmailAddress::from($config->replyToAddress));
+
+ $this->assertTrue($queue->send($email));
+ } else {
+ // Just to not create a test warning
+ $this->assertTrue(TRUE);
+ }
+ }
+
+ public function testSendWithDefault(): void {
+ if (getenv('EMAIL_TEST_SMTP') != NULL) {
+ $config = json_decode(getenv('EMAIL_TEST_SMTP'));
+ $queue = self::getEmailQueue(EmailQueue::DEFAULT);
+ $email = new Email();
+ $email->setSubject('testSendWithDefault');
+ $email->setBody(Email::HTML, 'EmailQueueTest::testSendWithReroute
This email shall have arrived at your normal mailbox: '.$config->targetAddress.'
');
+ $email->setBody(Email::TEXT, "EmailQueueTest::testSendWithReroute\n=================\n\nThis email shall have arrived at your target mailbox: ".$config->targetAddress."\n");
+ $email->addTo(EmailAddress::from($config->targetAddress));
+ if (isset($config->replyToAddress)) $email->setReplyTo(EmailAddress::from($config->replyToAddress));
+
+ $this->assertTrue($queue->send($email));
+ } else {
+ // Just to not create a test warning
+ $this->assertTrue(TRUE);
+ }
+ }
+
+ public function testQueueWithBlocked(): void {
+ if ((getenv('EMAIL_TEST_SMTP') != NULL) && (getenv('EMAIL_DATABASE') != NULL)) {
+ $config = json_decode(getenv('EMAIL_TEST_SMTP'));
+ $queue = self::getEmailQueue(EmailQueue::BLOCK);
+ $email = new Email();
+ $email->setSubject('[EmailQueueTest] testQueueWithBlocked');
+ $email->setBody(Email::HTML, 'EmailQueueTest::testQueueWithBlocked
This email shall not have been delivered! Test failed.
');
+ $email->setBody(Email::TEXT, "EmailQueueTest::testQueueWithBlocked\n=================\n\nThis email shall not have been delivered! Test failed.\n");
+ $email->addTo(EmailAddress::from($config->targetAddress));
+ if (isset($config->replyToAddress)) $email->setReplyTo(EmailAddress::from($config->replyToAddress));
+
+ $this->assertTrue($rc = $queue->queue($email));
+
+ // Now process the queue
+ $rc = $queue->processQueue();
+ $this->assertTrue($rc->sent >= 0);
+ } else {
+ // Just to not create a test warning
+ $this->assertTrue(TRUE);
+ }
+ }
+
+ public function testQueueWithReroute(): void {
+ if ((getenv('EMAIL_TEST_SMTP') != NULL) && (getenv('EMAIL_DATABASE') != NULL)) {
+ $config = json_decode(getenv('EMAIL_TEST_SMTP'));
+ $queue = self::getEmailQueue(EmailQueue::REROUTE);
+ $email = new Email();
+ $email->setSubject('testQueueWithReroute');
+ $email->setBody(Email::HTML, 'EmailQueueTest::testQueueWithReroute
This email shall have arrived at your reroute mailbox: '.self::$queueConfig->getRerouteConfig()->getRecipients()[0]->email.'
');
+ $email->setBody(Email::TEXT, "EmailQueueTest::testQueueWithReroute\n=================\n\nThis email shall have arrived at your reroute mailbox: ".self::$queueConfig->getRerouteConfig()->getRecipients()[0]->email."\n");
+ $email->addTo(EmailAddress::from($config->targetAddress));
+ if (isset($config->replyToAddress)) $email->setReplyTo(EmailAddress::from($config->replyToAddress));
+
+ $this->assertTrue($rc = $queue->queue($email));
+
+ // Now process the queue
+ $rc = $queue->processQueue();
+ $this->assertTrue($rc->sent >= 1);
+ } else {
+ // Just to not create a test warning
+ $this->assertTrue(TRUE);
+ }
+ }
+
+ public function testQueueWithBcc(): void {
+ if ((getenv('EMAIL_TEST_SMTP') != NULL) && (getenv('EMAIL_DATABASE') != NULL)) {
+ $config = json_decode(getenv('EMAIL_TEST_SMTP'));
+ $queue = self::getEmailQueue(EmailQueue::BCC);
+ $email = new Email();
+ $email->setSubject('testQueueWithBcc');
+ $email->setBody(Email::HTML, 'EmailQueueTest::testQueueWithBcc
This email shall have arrived at your BCC mailbox: '.self::$queueConfig->getBccConfig()->getRecipients()[0]->email.'
');
+ $email->setBody(Email::TEXT, "EmailQueueTest::testQueueWithBcc\n=================\n\nThis email shall have arrived at your target mailbox: ".self::$queueConfig->getBccConfig()->getRecipients()[0]->email."\n");
+ $email->addTo(EmailAddress::from($config->targetAddress));
+ if (isset($config->replyToAddress)) $email->setReplyTo(EmailAddress::from($config->replyToAddress));
+
+ $this->assertTrue($rc = $queue->queue($email));
+
+ // Now process the queue
+ $rc = $queue->processQueue();
+ $this->assertTrue($rc->sent >= 1);
+ } else {
+ // Just to not create a test warning
+ $this->assertTrue(TRUE);
+ }
+ }
+
+ public function testQueueWithDefault(): void {
+ if ((getenv('EMAIL_TEST_SMTP') != NULL) && (getenv('EMAIL_DATABASE') != NULL)) {
+ $config = json_decode(getenv('EMAIL_TEST_SMTP'));
+ $queue = self::getEmailQueue(EmailQueue::DEFAULT);
+ $email = new Email();
+ $email->setSubject('testQueueWithDefault');
+ $email->setBody(Email::HTML, 'EmailQueueTest::testQueueWithReroute
This email shall have arrived at your normal mailbox: '.$config->targetAddress.'
');
+ $email->setBody(Email::TEXT, "EmailQueueTest::testQueueWithReroute\n=================\n\nThis email shall have arrived at your target mailbox: ".$config->targetAddress."\n");
+ $email->addTo(EmailAddress::from($config->targetAddress));
+ if (isset($config->replyToAddress)) $email->setReplyTo(EmailAddress::from($config->replyToAddress));
+
+ $this->assertTrue($rc = $queue->queue($email));
+
+ // Now process the queue
+ $rc = $queue->processQueue();
+ $this->assertTrue($rc->sent >= 1);
+ } else {
+ // Just to not create a test warning
+ $this->assertTrue(TRUE);
+ }
+ }
+
+ public static function getMailDAO() {
+ Log::setDefaultLogLevel(Log::ERROR);
+ if ((self::$database == NULL) && (getenv('EMAIL_DATABASE') != NULL)) {
+ $config = json_decode(getenv('EMAIL_DATABASE'), TRUE);
+ self::$database = new Database($config);
+ self::$dao = new EmailsDAO(self::$database);
+ self::$dao->deleteBy();
+ }
+ return self::$dao;
+ }
+
+ public static function getEmailQueue($mailMode) {
+ if ((self::$queue == NULL) && getenv('EMAIL_TEST_SMTP') != NULL) {
+ self::$queueConfig = EmailConfig::from(getenv('EMAIL_TEST_SMTP'));
+ self::$queue = new EmailQueue(self::$queueConfig, self::getMailDAO());
+ }
+ if (self::$queueConfig != NULL) {
+ self::$queueConfig->setMailMode($mailMode);
+ }
+ return self::$queue;
+ }
+
+}
+
diff --git a/tests/TgEmail/EmailTest.php b/tests/TgEmail/EmailTest.php
new file mode 100644
index 0000000..18aabda
--- /dev/null
+++ b/tests/TgEmail/EmailTest.php
@@ -0,0 +1,139 @@
+setSender(EmailAddress::from('John Doe '));
+ $this->assertEquals('John Doe ', $email->getSender()->__toString());
+ }
+
+ public function testSetReplyTo(): void {
+ $email = new Email();
+ $email->setReplyTo(EmailAddress::from('John Doe '));
+ $this->assertEquals('John Doe ', $email->getReplyTo()->__toString());
+ }
+
+ public function testAddToWithString(): void {
+ $email = new Email();
+ $email->addTo('John Doe getTo();
+ $this->assertEquals(1, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ }
+
+ public function testAddToWithObject(): void {
+ $email = new Email();
+ $email->addTo(EmailAddress::from('John Doe getTo();
+ $this->assertEquals(1, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ }
+
+ public function testAddToWithArray(): void {
+ $email = new Email();
+ $email->addTo(array(
+ EmailAddress::from('John Doe getTo();
+ $this->assertEquals(2, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ $this->assertEquals('Jane Doe ', $recipients[1]->__toString());
+ }
+
+ public function testAddCcWithString(): void {
+ $email = new Email();
+ $email->addCc('John Doe getCc();
+ $this->assertEquals(1, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ }
+
+ public function testAddCcWithObject(): void {
+ $email = new Email();
+ $email->addCc(EmailAddress::from('John Doe getCc();
+ $this->assertEquals(1, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ }
+
+ public function testAddCcWithArray(): void {
+ $email = new Email();
+ $email->addCc(array(
+ EmailAddress::from('John Doe getCc();
+ $this->assertEquals(2, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ $this->assertEquals('Jane Doe ', $recipients[1]->__toString());
+ }
+
+ public function testAddBccWithString(): void {
+ $email = new Email();
+ $email->addBcc('John Doe getBcc();
+ $this->assertEquals(1, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ }
+
+ public function testAddBccWithObject(): void {
+ $email = new Email();
+ $email->addBcc(EmailAddress::from('John Doe getBcc();
+ $this->assertEquals(1, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ }
+
+ public function testAddBccWithArray(): void {
+ $email = new Email();
+ $email->addBcc(array(
+ EmailAddress::from('John Doe getBcc();
+ $this->assertEquals(2, count($recipients));
+ $this->assertEquals('John Doe ', $recipients[0]->__toString());
+ $this->assertEquals('Jane Doe ', $recipients[1]->__toString());
+ }
+
+ public function testSetSubject(): void {
+ $email = new Email();
+ $email->setSubject('A subject');
+ $this->assertEquals('A subject', $email->getSubject());
+ }
+
+ public function testSetHtmlBody(): void {
+ $email = new Email();
+ $email->setBody(Email::HTML, 'A HTML body text');
+ $this->assertEquals('A HTML body text', $email->getBody(Email::HTML));
+ }
+
+ public function testSetTextBody(): void {
+ $email = new Email();
+ $email->setBody(Email::TEXT, 'A plain body text');
+ $this->assertEquals('A plain body text', $email->getBody(Email::TEXT));
+ }
+
+
+}
+