Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add fake pop server and POP-before-SMTP tests.

Update POP before SMTP example to use new static method.
  • Loading branch information...
commit 73093a32a31f6a246261c8b4b920b352877a746d 1 parent 3374536
@Synchro authored
View
4 changelog.md
@@ -35,6 +35,10 @@
* Introduce autoloader
* Allow overriding of SMTP class
* Overhaul of PHPDocs
+* Fix broken Q-encoding
+* Czech language update (Thanks to @nemelu)
+* Removal of excess blank lines in messages
+* Added fake POP server and unit tests for POP-before-SMTP
## Version 5.2.6 (April 11th 2013)
* Reflect move to PHPMailer GitHub organisation at https://github.com/PHPMailer/PHPMailer
View
56 class.pop3.php
@@ -56,6 +56,7 @@ class POP3
* POP3 Carriage Return + Line Feed.
* @type string
* @access public
+ * @deprecated Use the constant instead
*/
public $CRLF = "\r\n";
@@ -124,9 +125,13 @@ class POP3
private $error;
/**
+ * Line break constant
+ */
+ const CRLF = "\r\n";
+
+ /**
* Constructor.
* @access public
- * @access private
*/
public function __construct()
{
@@ -136,6 +141,21 @@ public function __construct()
}
/**
+ * Simple static wrapper for all-in-one POP before SMTP
+ * @param $host
+ * @param bool $port
+ * @param bool $tval
+ * @param string $username
+ * @param string $password
+ * @return bool
+ */
+ public static function popBeforeSmtp($host, $port = false, $tval = false, $username = '', $password = '')
+ {
+ $pop = new POP3;
+ return $pop->authorise($host, $port, $tval, $username, $password);
+ }
+
+ /**
* Authenticate with a POP3 server.
* A connect, login, disconnect sequence
* appropriate for POP-before SMTP authorisation.
@@ -151,14 +171,14 @@ public function __construct()
public function authorise($host, $port = false, $tval = false, $username = '', $password = '', $debug_level = 0)
{
$this->host = $host;
- // If no port value is passed, retrieve it
- if ($port == false) {
+ // If no port value provided, use default
+ if ($port === false) {
$this->port = $this->POP3_PORT;
} else {
$this->port = $port;
}
- // If no port value is passed, retrieve it
- if ($tval == false) {
+ // If no timeout value provided, use default
+ if ($tval === false) {
$this->tval = $this->POP3_TIMEOUT;
} else {
$this->tval = $tval;
@@ -177,7 +197,7 @@ public function authorise($host, $port = false, $tval = false, $username = '', $
return true;
}
}
- // We need to disconnect regardless if the login succeeded
+ // We need to disconnect regardless of whether the login succeeded
$this->disconnect();
return false;
}
@@ -274,14 +294,13 @@ public function login($username = '', $password = '')
if (empty($password)) {
$password = $this->password;
}
- $pop_username = "USER $username" . $this->CRLF;
- $pop_password = "PASS $password" . $this->CRLF;
- // send the Username
- $this->sendString($pop_username);
+
+ // Send the Username
+ $this->sendString("USER $username" . self::CRLF);
$pop3_response = $this->getResponse();
if ($this->checkResponse($pop3_response)) {
- // send the Password
- $this->sendString($pop_password);
+ // Send the Password
+ $this->sendString("PASS $password" . self::CRLF);
$pop3_response = $this->getResponse();
if ($this->checkResponse($pop3_response)) {
return true;
@@ -297,7 +316,9 @@ public function login($username = '', $password = '')
public function disconnect()
{
$this->sendString('QUIT');
- fclose($this->pop_conn);
+ //The QUIT command may cause the daemon to exit, which will kill our connection
+ //So ignore errors here
+ @fclose($this->pop_conn);
}
/**
@@ -309,8 +330,7 @@ public function disconnect()
*/
private function getResponse($size = 128)
{
- $pop3_response = fgets($this->pop_conn, $size);
- return $pop3_response;
+ return fgets($this->pop_conn, $size);
}
/**
@@ -321,8 +341,10 @@ private function getResponse($size = 128)
*/
private function sendString($string)
{
- $bytes_sent = fwrite($this->pop_conn, $string, strlen($string));
- return $bytes_sent;
+ if ($this->pop_conn) {
+ return fwrite($this->pop_conn, $string, strlen($string));
+ }
+ return 0;
}
/**
View
6 examples/pop_before_smtp.phps
@@ -8,12 +8,10 @@
<?php
require '../PHPMailerAutoload.php';
-//Create a new POP client instance
-$pop = new POP3();
-//authenticate via POP
-$pop->authorise('pop3.yourdomain.com', 110, 30, 'username', 'password', 1);
+//Authenticate via POP3
//Now you should be clear to submit messages over SMTP for a while
//Only applies if your host supports POP-before-SMTP
+$pop = POP3::popBeforeSmtp('pop3.example.com', 110, 30, 'username', 'password', 1);
//Create a new PHPMailer instance
//Passing true to the constructor enables the use of exceptions for error handling
View
125 test/fakepopserver.sh
@@ -0,0 +1,125 @@
+#!/usr/bin/env bash
+
+# Fake POP3 server
+# By Marcus Bointon <phpmailer@synchromedia.co.uk>
+# Based on code by 'Frater' found at http://www.linuxquestions.org/questions/programming-9/fake-pop3-server-to-capture-pop3-passwords-933733
+# Does not actually serve any mail, but supports commands sufficient to test POP-before SMTP
+# Can be run directly from a shell like this:
+# mkfifo fifo; nc -l 1100 <fifo |./fakepopserver.sh >fifo; rm fifo
+# It will accept any user name and will return a positive response for the password 'test'
+
+# Licensed under the GNU Lesser General Public License: http://www.gnu.org/copyleft/lesser.html
+
+# Enable debug output
+#set -xv
+export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
+
+LOGFOLDER=/tmp
+
+LOGFILE=${LOGFOLDER}/fakepop.log
+
+LOGGING=1
+DEBUG=1
+TIMEOUT=10
+
+POP_USER=
+POP_PASSWRD=test
+
+LINES=1
+BREAK=0
+
+write_log () {
+ if [ ${LINES} -eq 1 ] ; then
+ echo '---' >>${LOGFILE}
+ fi
+ let LINES+=1
+ [ ${LOGGING} = 0 ] || echo -e "`date '+%b %d %H:%M'` pop3 $*" >>${LOGFILE}
+}
+
+ANSWER="+OK Fake POP3 Service Ready"
+
+while [ ${BREAK} -eq 0 ] ; do
+ echo -en "${ANSWER}\r\n"
+
+ REPLY=""
+
+ #Input appears in $REPLY
+ read -t ${TIMEOUT}
+
+ ANSWER="+OK "
+ COMMAND=""
+ ARGS=""
+ TIMEOUT=30
+
+ if [ "$REPLY" ] ; then
+ write_log "RAW input: '`echo "${REPLY}" | tr -cd '[ -~]'`'"
+
+ COMMAND="`echo "${REPLY}" | awk '{print $1}' | tr -cd '\40-\176' | tr 'a-z' 'A-Z'`"
+ ARGS="`echo "${REPLY}" | tr -cd '\40-\176' | awk '{for(i=2;i<=NF;i++){printf "%s ", $i};printf "\n"}' | sed 's/ $//'`"
+
+ write_log "Command: \"${COMMAND}\""
+ write_log "Arguments: \"${ARGS}\""
+
+ case "$COMMAND" in
+ QUIT)
+ break
+ ;;
+ USER)
+ if [ -n "${ARGS}" ] ; then
+ POP_USER="${ARGS}"
+ ANSWER="+OK Please send PASS command"
+ fi
+ ;;
+ AUTH)
+ ANSWER="+OK \r\n."
+ ;;
+ CAPA)
+ ANSWER="+OK Capabilities include\r\nUSER\r\nCAPA\r\n."
+ ;;
+ PASS)
+ if [ "${POP_PASSWRD}" == "${ARGS}" ] ; then
+ ANSWER="+OK Logged in.\r\n"
+ AUTH=1
+ else
+ ANSWER="-ERR Login failed\r\n"
+ fi
+ ;;
+ LIST)
+ if [ "${AUTH}" = 0 ] ; then
+ ANSWER="-ERR Not authenticated"
+ else
+ if [ -z "${ARGS}" ] ; then
+ ANSWER="+OK No messages, really\r\n."
+ else
+ ANSWER="-ERR No messages, no list, no status"
+ fi
+ fi
+ ;;
+ RSET)
+ ANSWER="+OK Resetting or whatever\r\n."
+ ;;
+ LAST)
+ if [ "${AUTH}" = 0 ] ; then
+ ANSWER="-ERR Not authenticated"
+ else
+ ANSWER="+OK 0"
+ fi
+ ;;
+ STAT)
+ if [ "${AUTH}" = 0 ] ; then
+ ANSWER="-ERR Not authenticated"
+ else
+ ANSWER="+OK 0 0"
+ fi
+ ;;
+ NOOP)
+ ANSWER="+OK Hang on, doing nothing"
+ ;;
+ esac
+ else
+ echo "+OK Connection timed out\r\n"
+ break
+ fi
+done
+
+echo "+OK Bye!\r\n"
View
49 test/phpmailerTest.php
@@ -59,6 +59,13 @@ class PHPMailerTest extends PHPUnit_Framework_TestCase
public $INCLUDE_DIR = '../';
/**
+ * PIDs of any processes we need to kill
+ * @type array
+ * @access private
+ */
+ private $pids = array();
+
+ /**
* Run before each test is started.
*/
public function setUp()
@@ -121,6 +128,11 @@ public function tearDown()
$this->Mail = null;
$this->ChangeLog = array();
$this->NoteLog = array();
+
+ foreach ($this->pids as $pid) {
+ $p = escapeshellarg($pid);
+ shell_exec("ps $p && kill -TERM $p");
+ }
}
@@ -1136,7 +1148,7 @@ public function testBCCAddressing()
}
/**
- * Encoding tests
+ * Encoding and charset tests
*/
public function testEncodings()
{
@@ -1170,6 +1182,13 @@ public function testEncodings()
);
}
+ public function testBase64()
+ {
+ $this->Mail->Subject .= ': Base-64 encoding';
+ $this->Mail->Encoding = 'base64';
+ $this->buildBody();
+ $this->assertTrue($this->Mail->send(), 'Base64 encoding failed');
+ }
/**
* S/MIME Signing tests
*/
@@ -1260,6 +1279,34 @@ public function testLineBreaks()
}
/**
+ * Use a fake POP3 server to test POP-before-SMTP auth
+ */
+ public function testPopBeforeSmtp()
+ {
+ //Start a fake POP server
+ $pid = shell_exec('nohup ./runfakepopserver.sh >/dev/null 2>/dev/null & printf "%u" $!');
+ $this->pids[] = $pid;
+
+ //Test a known-good login
+ $this->assertTrue(
+ POP3::popBeforeSmtp('localhost', 1100, 10, 'user', 'test'),
+ 'POP before SMTP failed'
+ );
+ //Kill the fake server
+ shell_exec('kill -TERM '.escapeshellarg($pid));
+
+ $pid = shell_exec('nohup ./runfakepopserver.sh >/dev/null 2>/dev/null & printf "%u" $!');
+ $this->pids[] = $pid;
+
+ //Test a known-bad login
+ $this->assertFalse(
+ POP3::popBeforeSmtp('localhost', 1100, 10, 'user', 'xxx'),
+ 'POP before SMTP should have failed'
+ );
+ shell_exec('kill -TERM '.escapeshellarg($pid));
+ }
+
+ /**
* Miscellaneous calls to improve test coverage and some small tests
*/
public function testMiscellaneous()
View
9 test/runfakepopserver.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+# Run the fake pop server from bash
+# Idea from http://blog.ale-re.net/2007/09/ipersimple-remote-shell-with-netcat.html
+# Defaults to port 1100 so it can be run by unpriv users and not clash with a real server
+
+mkfifo fifo
+nc -l 1100 <fifo |bash ./fakepopserver.sh >fifo
+rm fifo
Please sign in to comment.
Something went wrong with that request. Please try again.