Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'build/integration/features/bootstrap/FakeSMTPHelper.php')
-rw-r--r--build/integration/features/bootstrap/FakeSMTPHelper.php159
1 files changed, 159 insertions, 0 deletions
diff --git a/build/integration/features/bootstrap/FakeSMTPHelper.php b/build/integration/features/bootstrap/FakeSMTPHelper.php
new file mode 100644
index 00000000000..9a64b6d31de
--- /dev/null
+++ b/build/integration/features/bootstrap/FakeSMTPHelper.php
@@ -0,0 +1,159 @@
+<?php
+
+// Code below modified from https://github.com/axllent/fake-smtp/blob/f0856f8a0df6f4ca5a573cf31428c09ebc5b9ea3/fakeSMTP.php,
+// which is under the MIT license (https://github.com/axllent/fake-smtp/blob/f0856f8a0df6f4ca5a573cf31428c09ebc5b9ea3/LICENSE)
+
+/**
+ * fakeSMTP - A PHP / inetd fake smtp server.
+ * Allows client<->server interaction
+ * The comunication is based upon the SMPT standards defined in http://www.lesnikowski.com/mail/Rfc/rfc2821.txt
+ */
+
+class fakeSMTP {
+ public $logFile = false;
+ public $serverHello = 'fakeSMTP ESMTP PHP Mail Server Ready';
+
+ public function __construct($fd) {
+ $this->mail = [];
+ $this->mail['ipaddress'] = false;
+ $this->mail['emailSender'] = '';
+ $this->mail['emailRecipients'] = [];
+ $this->mail['emailSubject'] = false;
+ $this->mail['rawEmail'] = false;
+ $this->mail['emailHeaders'] = false;
+ $this->mail['emailBody'] = false;
+
+ $this->fd = $fd;
+ }
+
+ public function receive() {
+ $hasValidFrom = false;
+ $hasValidTo = false;
+ $receivingData = false;
+ $header = true;
+ $this->reply('220 '.$this->serverHello);
+ $this->mail['ipaddress'] = $this->detectIP();
+ while ($data = fgets($this->fd)) {
+ $data = preg_replace('@\r\n@', "\n", $data);
+
+ if (!$receivingData) {
+ $this->log($data);
+ }
+
+ if (!$receivingData && preg_match('/^MAIL FROM:\s?<(.*)>/i', $data, $match)) {
+ if (preg_match('/(.*)@\[.*\]/i', $match[1]) || $match[1] != '' || $this->validateEmail($match[1])) {
+ $this->mail['emailSender'] = $match[1];
+ $this->reply('250 2.1.0 Ok');
+ $hasValidFrom = true;
+ } else {
+ $this->reply('551 5.1.7 Bad sender address syntax');
+ }
+ } elseif (!$receivingData && preg_match('/^RCPT TO:\s?<(.*)>/i', $data, $match)) {
+ if (!$hasValidFrom) {
+ $this->reply('503 5.5.1 Error: need MAIL command');
+ } else {
+ if (preg_match('/postmaster@\[.*\]/i', $match[1]) || $this->validateEmail($match[1])) {
+ array_push($this->mail['emailRecipients'], $match[1]);
+ $this->reply('250 2.1.5 Ok');
+ $hasValidTo = true;
+ } else {
+ $this->reply('501 5.1.3 Bad recipient address syntax '.$match[1]);
+ }
+ }
+ } elseif (!$receivingData && preg_match('/^RSET$/i', trim($data))) {
+ $this->reply('250 2.0.0 Ok');
+ $hasValidFrom = false;
+ $hasValidTo = false;
+ } elseif (!$receivingData && preg_match('/^NOOP$/i', trim($data))) {
+ $this->reply('250 2.0.0 Ok');
+ } elseif (!$receivingData && preg_match('/^VRFY (.*)/i', trim($data), $match)) {
+ $this->reply('250 2.0.0 '.$match[1]);
+ } elseif (!$receivingData && preg_match('/^DATA/i', trim($data))) {
+ if (!$hasValidTo) {
+ $this->reply('503 5.5.1 Error: need RCPT command');
+ } else {
+ $this->reply('354 Ok Send data ending with <CRLF>.<CRLF>');
+ $receivingData = true;
+ }
+ } elseif (!$receivingData && preg_match('/^(HELO|EHLO)/i', $data)) {
+ $this->reply('250 HELO '.$this->mail['ipaddress']);
+ } elseif (!$receivingData && preg_match('/^QUIT/i', trim($data))) {
+ break;
+ } elseif (!$receivingData) {
+ //~ $this->reply('250 Ok');
+ $this->reply('502 5.5.2 Error: command not recognized');
+ } elseif ($receivingData && $data == ".\n") {
+ /* Email Received, now let's look at it */
+ $receivingData = false;
+ $this->reply('250 2.0.0 Ok: queued as '.$this->generateRandom(10));
+ $splitmail = explode("\n\n", $this->mail['rawEmail'], 2);
+ if (count($splitmail) == 2) {
+ $this->mail['emailHeaders'] = $splitmail[0];
+ $this->mail['emailBody'] = $splitmail[1];
+ $headers = preg_replace("/ \s+/", ' ', preg_replace("/\n\s/", ' ', $this->mail['emailHeaders']));
+ $headerlines = explode("\n", $headers);
+ for ($i=0; $i<count($headerlines); $i++) {
+ if (preg_match('/^Subject: (.*)/i', $headerlines[$i], $matches)) {
+ $this->mail['emailSubject'] = trim($matches[1]);
+ }
+ }
+ } else {
+ $this->mail['emailBody'] = $splitmail[0];
+ }
+ set_time_limit(5); // Just run the exit to prevent open threads / abuse
+ } elseif ($receivingData) {
+ $this->mail['rawEmail'] .= $data;
+ }
+ }
+ /* Say good bye */
+ $this->reply('221 2.0.0 Bye '.$this->mail['ipaddress']);
+
+ fclose($this->fd);
+ }
+
+ public function log($s) {
+ if ($this->logFile) {
+ file_put_contents($this->logFile, trim($s)."\n", FILE_APPEND);
+ }
+ }
+
+ private function reply($s) {
+ $this->log("REPLY:$s");
+ fwrite($this->fd, $s . "\r\n");
+ }
+
+ private function detectIP() {
+ $raw = explode(':', stream_socket_get_name($this->fd, true));
+ return $raw[0];
+ }
+
+ private function validateEmail($email) {
+ return preg_match('/^[_a-z0-9-+]+(\.[_a-z0-9-+]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/', strtolower($email));
+ }
+
+ private function generateRandom($length=8) {
+ $password = '';
+ $possible = '2346789BCDFGHJKLMNPQRTVWXYZ';
+ $maxlength = strlen($possible);
+ $i = 0;
+ for ($i=0; $i < $length; $i++) {
+ $char = substr($possible, mt_rand(0, $maxlength-1), 1);
+ if (!strstr($password, $char)) {
+ $password .= $char;
+ }
+ }
+ return $password;
+ }
+}
+
+$socket = stream_socket_server('tcp://127.0.0.1:2525', $errno, $errstr);
+if (!$socket) {
+ exit();
+}
+
+while ($fd = stream_socket_accept($socket)) {
+ $fakeSMTP = new fakeSMTP($fd);
+ $fakeSMTP->receive();
+}
+
+fclose($socket);