From 0a8e57863ecbae43724ebc9b68b8950e59bbc8a7 Mon Sep 17 00:00:00 2001
From: Cameron <e107inc@gmail.com>
Date: Mon, 18 May 2015 11:49:32 -0700
Subject: [PATCH] Fixes for resend activation email. (frontend). Resend to all
 (backend). Fixes broken link to "resend activation" in login error messages.

---
 e107_admin/users.php                          |  26 ++-
 e107_handlers/cron_class.php                  |  24 +-
 e107_handlers/login.php                       | 153 ++++++++-----
 e107_handlers/mail_manager_class.php          |  85 +++----
 e107_handlers/user_handler.php                |  38 +++-
 .../login_menu/login_menu_shortcodes.php      |   8 +-
 fpw.php                                       |   9 +-
 signup.php                                    | 213 ++++++++++--------
 8 files changed, 354 insertions(+), 202 deletions(-)

diff --git a/e107_admin/users.php b/e107_admin/users.php
index e3c63f483..ba66ae914 100644
--- a/e107_admin/users.php
+++ b/e107_admin/users.php
@@ -301,7 +301,8 @@ class users_admin_ui extends e_admin_ui
 		{
 			$resetPasswords = !empty($_POST['resetPasswords']);
 			$age = vartrue($_POST['resendAge'], 24);
-			$this->resend_to_all($resetPasswords, $age);
+			$class = vartrue($_POST['resendClass'], false);
+			$this->resend_to_all($resetPasswords, $age, $class);
 		}
 
 		
@@ -1851,7 +1852,7 @@ class users_admin_ui extends e_admin_ui
 		<tr><td>".$caption."<td>
 		<td>
 		<div>Older than ".$frm->select('resendAge', $age, 24).$frm->checkbox('resetPasswords',1,false,'Reset all passwords').
-
+		$frm->userclass('resendClass',false, null ).
 		$frm->button('resendToAll', 1, 'warning', LAN_GO)."
 
 
@@ -1873,7 +1874,7 @@ class users_admin_ui extends e_admin_ui
 	 * @param bool $resetPasswords
 	 * @param int $age in hours. ie. older than 24 hours will be sent an email.
 	 */
-	function resend_to_all($resetPasswords=false, $age=24)
+	function resend_to_all($resetPasswords=false, $age=24, $class='')
 	{
 		global $sql,$pref;
 		$tp = e107::getParser();
@@ -1890,7 +1891,14 @@ class users_admin_ui extends e_admin_ui
 	//	$query = "SELECT u.*, ue.* FROM `#user` AS u LEFT JOIN `#user_extended` AS ue ON ue.user_extended_id = u.user_id WHERE u.user_ban = 2 AND u.user_email != '' AND u.user_join < ".$age." ORDER BY u.user_id DESC";
 
 
-		$query = "SELECT u.* FROM `#user` AS u WHERE u.user_ban = 2 AND u.user_email != '' AND u.user_join < ".$age." ORDER BY u.user_id DESC";
+		$query = "SELECT u.* FROM `#user` AS u WHERE u.user_ban = 2 AND u.user_email != '' AND u.user_join < ".$age." ";
+
+		if(!empty($class))
+		{
+			$query .= " AND FIND_IN_SET( ".intval($class).", u.user_class) ";
+		}
+
+		$query .= " ORDER BY u.user_id DESC";
 
 		$sql->gen($query);
 
@@ -1946,11 +1954,11 @@ class users_admin_ui extends e_admin_ui
 					'USERID'		        => $row['user_id'],
 					'LOGINNAME'             => (intval($emailLogin) === 1) ? $row['user_email'] : $row['user_loginname'],
 					'PASSWORD'              => $rawPassword,
-					'DISPLAYNAME' 	        => $row['user_name'],
+					'DISPLAYNAME' 	        => $tp->toDB($row['user_name']),
 					'SUBJECT'               => LAN_SIGNUP_98,
 					'USERNAME' 		        => $row['user_name'],
 					'USERLASTVISIT'         => $row['user_lastvisit'],
-					'ACTIVATION_LINK'       => "<a href='".$activationUrl."'>".$activationUrl."</a>",
+					'ACTIVATION_LINK'       => '<a href="'.$activationUrl.'">'.$activationUrl.'</a>', // Warning: switching the quotes on this will break the template.
 					'ACTIVATION_URL'        => $activationUrl,
 					'DATE_SHORT'            => $tp->toDate(time(),'short'),
 					'DATE_LONG'             => $tp->toDate(time(),'long'),
@@ -1983,10 +1991,12 @@ class users_admin_ui extends e_admin_ui
 		);
 
 
-		$mailer->sendEmails('signup', $mailData, $recipients);
+		$mailer->sendEmails('signup', $mailData, $recipients, array('mail_force_queue'=>1));
 		$totalMails = count($recipients);
 
-		e107::getMessage()->addSuccess("Total emails added to mail queue: ".$totalMails);
+		$url = e_ADMIN."mailout.php?mode=pending&action=list";
+
+		e107::getMessage()->addSuccess("Total emails added to <a href='".$url."'>mail queue</a>: ".$totalMails);
 
 	}
 
diff --git a/e107_handlers/cron_class.php b/e107_handlers/cron_class.php
index 040c99b11..3b0247459 100644
--- a/e107_handlers/cron_class.php
+++ b/e107_handlers/cron_class.php
@@ -171,8 +171,17 @@ class _system_cron
 
 	    sendemail($pref['siteadminemail'], "e107 - TEST Email Sent by cron.".date("r"), $message, $pref['siteadmin'],$pref['siteadminemail'], $pref['siteadmin']);
 	}
-	
-	function procEmailQueue()
+
+
+	/**
+	 * Process the Mail Queue
+	 * First create a mail queue then debug with the following:
+	   require_once(e_HANDLER."cron_class.php");
+	   $cron = new _system_cron;
+	   $cron->procEmailQueue(true);
+	 * @param bool $debug
+	 */
+	function procEmailQueue($debug= false)
 	{
 
 		$sendPerHit = e107::getConfig()->get('mail_workpertick',5);
@@ -183,9 +192,14 @@ class _system_cron
 		{
 			e107::getLog()->e_log_event(10,debug_backtrace(),'DEBUG','CRON Email','Email run started',FALSE,LOG_TO_ROLLING);
 		}
-		
-		require_once(e_HANDLER.'mail_manager_class.php');
-		$mailManager = new e107MailManager();
+
+		$mailManager = e107::getBulkEmail();
+
+		if($debug === true)
+		{
+			$mailManager->controlDebug(1);
+		}
+
 		$mailManager->doEmailTask($sendPerHit,$pauseCount,$pauseTime);
 		
 		if (CRON_MAIL_DEBUG)
diff --git a/e107_handlers/login.php b/e107_handlers/login.php
index c9946db6b..00c5ee257 100644
--- a/e107_handlers/login.php
+++ b/e107_handlers/login.php
@@ -43,9 +43,10 @@ class userlogin
 	protected $e107;
 	protected $userMethods;			// Pointer to user handler
 	protected $userIP;				// IP address
-	protected $lookEmail = FALSE;	// Flag set if logged in using email address
+	protected $lookEmail = false;	// Flag set if logged in using email address
 	protected $userData = array();	// Information for current user
-	protected $passResult = FALSE;	// USed to determine if stored password needs update
+	protected $passResult = false;	// USed to determine if stored password needs update
+	protected $testMode   = false;
 
 
 	public function __construct()
@@ -452,6 +453,35 @@ class userlogin
 	}
 
 
+	public function test()
+	{
+
+		$this->testMode = true;
+		$errors = array(
+			'LOGIN_TRY_OTHER'=> 2,		// Try some other authentication method
+			'LOGIN_CONTINUE'=>1,		// Not rejected (which is not exactly the same as 'accepted') by alt_auth
+			'LOGIN_ABORT'=>-1,			// Rejected by alt_auth
+			'LOGIN_BAD_PW'=> -2,		// Password wrong
+			'LOGIN_BAD_USER'=> -3,		// User not in DB
+			'LOGIN_BAD_USERNAME'=> -4,	// Username format unacceptable (e.g. too long)
+			'LOGIN_BAD_CODE'=> -5,		// Wrong image code entered
+			'LOGIN_MULTIPLE'=> -6, 		// Error if multiple logins not allowed
+			'LOGIN_NOT_ACTIVATED'=> -7,	// User in DB=> not activated
+			'LOGIN_BLANK_FIELD'=> -8,	// Username or password blank
+			'LOGIN_BAD_TRIGGER'=> -9,	// Rejected by trigger event
+			'LOGIN_BANNED'=> -10,		// Banned user attempting login
+			'LOGIN_CHAP_FAIL'=> -11,	// CHAP login failed
+			'LOGIN_DB_ERROR'=> -12,		// Error adding user to main DB
+		);
+
+		foreach($errors as $k=>$v)
+		{
+			$this->invalidLogin("John Smith", $v, 'Custom error text');
+			echo "<h4>".$k."</h4>";
+			echo e107::getMessage()->render();
+		}
+
+	}
 
 	/**
 	 * called to log the reason for a failed login.
@@ -463,76 +493,85 @@ class userlogin
 		global $pref, $sql;
 
 		$doCheck = FALSE;			// Flag set if need to ban check
-		switch ($reason)
+
+
+		switch($reason)
 		{
-			case LOGIN_ABORT :		// alt_auth reject
-			  define("LOGINMESSAGE", LAN_LOGIN_21);
-			  $this->genNote($this->userIP,$username, 'Alt_auth: '.LAN_LOGIN_14);
-			  $this->logNote('LAN_ROLL_LOG_04', 'Alt_Auth: '.$username);
-			  $doCheck = TRUE;
-			  break;
-			case LOGIN_DB_ERROR :	// alt_auth couldn't add valid user
-				define("LOGINMESSAGE", LAN_LOGIN_31);
-				$this->genNote($username, 'Alt_auth: '.LAN_LOGIN_30);
+			case LOGIN_ABORT :        // alt_auth reject
+				$message = LAN_LOGIN_21;
+				$this->genNote($this->userIP, $username, 'Alt_auth: ' . LAN_LOGIN_14);
+				$this->logNote('LAN_ROLL_LOG_04', 'Alt_Auth: ' . $username);
+				$doCheck = true;
+				break;
+			case LOGIN_DB_ERROR :    // alt_auth couldn't add valid user
+				$message = LAN_LOGIN_31;
+				$this->genNote($username, 'Alt_auth: ' . LAN_LOGIN_30);
 //				$this->logNote('LAN_ROLL_LOG_04', 'Alt_Auth: '.$username);	// Added in alt_auth login
-				$doCheck = TRUE;
+				$doCheck = true;
 				break;
 			case LOGIN_BAD_PW :
-			  define("LOGINMESSAGE", LAN_LOGIN_21);
-			  $this->logNote('LAN_ROLL_LOG_03', $username);
-			  break;
+				$message = LAN_LOGIN_21;
+				$this->logNote('LAN_ROLL_LOG_03', $username);
+				break;
 			case LOGIN_CHAP_FAIL :
-			  define("LOGINMESSAGE", LAN_LOGIN_21);
-			  $this->logNote('LAN_ROLL_LOG_03', 'CHAP: '.$username);
-			  break;
+				$message = LAN_LOGIN_21;
+				$this->logNote('LAN_ROLL_LOG_03', 'CHAP: ' . $username);
+				break;
 			case LOGIN_BAD_USER :
-			  define("LOGINMESSAGE", LAN_LOGIN_21);
-			  $this->genNote($username, LAN_LOGIN_14);
-			  $this->logNote('LAN_ROLL_LOG_04', $username);
-			  $doCheck = TRUE;
-			  break;
+				$message = LAN_LOGIN_21;
+				$this->genNote($username, LAN_LOGIN_14);
+				$this->logNote('LAN_ROLL_LOG_04', $username);
+				$doCheck = true;
+				break;
 			case LOGIN_BAD_USERNAME :
-			  define("LOGINMESSAGE", LAN_LOGIN_21);
-			  $this->logNote('LAN_ROLL_LOG_08', $username);
-			  break;
+				$message = LAN_LOGIN_21;
+				$this->logNote('LAN_ROLL_LOG_08', $username);
+				break;
 			case LOGIN_MULTIPLE :
-			  define("LOGINMESSAGE", LAN_LOGIN_24);
-			  $this->logNote('LAN_ROLL_LOG_07', "U: {$username} IP: {$this->userIP}");
-			  $this->genNote($username, LAN_LOGIN_16);
-			  $doCheck = TRUE;
-			  break;
+				$message = LAN_LOGIN_24;
+				$this->logNote('LAN_ROLL_LOG_07', "U: {$username} IP: {$this->userIP}");
+				$this->genNote($username, LAN_LOGIN_16);
+				$doCheck = true;
+				break;
 			case LOGIN_BAD_CODE :
-			  define("LOGINMESSAGE", LAN_LOGIN_23);
-			  $this->logNote('LAN_ROLL_LOG_02', $username);
-			  break;
+				$message = LAN_LOGIN_23;
+				$this->logNote('LAN_ROLL_LOG_02', $username);
+				break;
 			case LOGIN_NOT_ACTIVATED :
-			  $srch = array("[","]");
-			  $repl = array("<a href='".e_BASE_ABS."signup.php?resend'>","</a>");
-			  define("LOGINMESSAGE", str_replace($srch,$repl,LAN_LOGIN_22));
-			  $this->logNote('LAN_ROLL_LOG_05', $username);
-			  $this->genNote($username, LAN_LOGIN_27);
-			  $doCheck = TRUE;
-			  break;
+				$srch = array("[", "]");
+				$repl = array("<a href='" . e_HTTP . "signup.php?resend'>", "</a>");
+				$message = str_replace($srch, $repl, LAN_LOGIN_22);
+				$this->logNote('LAN_ROLL_LOG_05', $username);
+				$this->genNote($username, LAN_LOGIN_27);
+				$doCheck = true;
+				break;
 			case LOGIN_BLANK_FIELD :
-			  define("LOGINMESSAGE", LAN_LOGIN_20);
-			  $this->logNote('LAN_ROLL_LOG_01', $username);
-			  break;
+				$message = LAN_LOGIN_20;
+				$this->logNote('LAN_ROLL_LOG_01', $username);
+				break;
 			case LOGIN_BAD_TRIGGER :
-			  define("LOGINMESSAGE", $extra_text);
-			  $this->logNote('LAN_ROLL_LOG_06', $username);
-			  break;
+				$message = $extra_text;
+				$this->logNote('LAN_ROLL_LOG_06', $username);
+				break;
 			case LOGIN_BANNED :
-			  define("LOGINMESSAGE", LAN_LOGIN_21);		// Just give 'incorrect login' message
-			  $this->genNote($username, LAN_LOGIN_25);
-			  $this->logNote('LAN_ROLL_LOG_09', $username);
-			  break;
-			default :		// Something's gone wrong!
-			  define("LOGINMESSAGE", LAN_LOGIN_21);		// Just give 'incorrect login' message
-			  $this->genNote($username, LAN_LOGIN_26);
-			  $this->logNote('LAN_ROLL_LOG_10', $username);
+				$message = LAN_LOGIN_21;        // Just give 'incorrect login' message
+				$this->genNote($username, LAN_LOGIN_25);
+				$this->logNote('LAN_ROLL_LOG_09', $username);
+				break;
+			default :        // Something's gone wrong!
+				$message = LAN_LOGIN_21;        // Just give 'incorrect login' message
+				$this->genNote($username, LAN_LOGIN_26);
+				$this->logNote('LAN_ROLL_LOG_10', $username);
 		}
 
-		e107::getMessage()->addError(LOGINMESSAGE);	
+		e107::getMessage()->addError($message);
+
+		if($this->testMode === true)
+		{
+			return $message;
+		}
+
+		define('LOGINMESSAGE', $message);
 
 		if ($doCheck) // See if ban required (formerly the checkibr() function)
 		{
diff --git a/e107_handlers/mail_manager_class.php b/e107_handlers/mail_manager_class.php
index 42427d323..e3ce56ff6 100644
--- a/e107_handlers/mail_manager_class.php
+++ b/e107_handlers/mail_manager_class.php
@@ -223,7 +223,7 @@ class e107MailManager
 		
 		if(deftrue('e_DEBUG'))
 		{
-			$this->debugMode = true; 	
+			$this->debugMode = true;
 		}
 		
 		if($this->debugMode === true)
@@ -426,13 +426,14 @@ class e107MailManager
 	 * @param $data - array of DB-sourced target-related data
 	 * @param $addMissing - if TRUE, undefined fields are added
 	 *
-	 * @return void
+	 * @return array
 	 */
 	public function dbToBoth(&$data, $addMissing = FALSE)
 	{	
 		$res = array();
 		$oneToOne = array_merge($this->dbTypes['mail_content'], $this->dbTypes['mail_recipients']);		// List of valid elements
 
+
 		// Start with simple 'one to one' fields
 		foreach ($oneToOne as $f => $v)
 		{
@@ -465,7 +466,9 @@ class e107MailManager
 		}
 		if (isset($data['mail_target_info']))
 		{
-			$tmp = e107::unserialize(str_replace('\\\'', '\'',$data['mail_target_info']));	// May have escaped data
+			$clean = stripslashes($data['mail_target_info']);
+			$tmp = e107::unserialize($clean);	// May have escaped data
+
 			$res['mail_target_info'] = $tmp;
 		}
 		
@@ -654,11 +657,12 @@ class e107MailManager
 	{
 		$counterList = array('mail_source_id','mail_togo_count', 'mail_sent_count', 'mail_fail_count', 'mail_start_send');
 
-		if (($email = $this->getNextEmail()) === FALSE)
+		if (($email = $this->getNextEmail()) === false)
 		{
-			return FALSE;
+			return false;
 		}
 
+
 		/**
 		 *	The $email variable has all the email data in 'flat' form, including that of the current recipient.
 		 *	field $email['mail_target_info'] has variable substitution information relating to the current recipient
@@ -713,17 +717,23 @@ class e107MailManager
 		
 		$mailToSend = $this->makeEmailBlock($email);			// Substitute mail-specific variables, attachments etc
 
-//		print_a($email);
+
 
 		if($this->debugMode)
 		{
+
+			echo "<h3>Preview</h3>";
+			$preview = $this->mailer->preview($mailToSend);
+			echo $preview;
+			echo "<h3>Preview (HTML)</h3>";
+			print_a($preview);
 			$logName = "mailout_simulation_".$email['mail_source_id'];
 			e107::getLog()->addDebug("Sending Email to <".$email['mail_recipient_name']."> ".$email['mail_recipient_email'])->toFile($logName,'Mailout Simulation Log',true);	
 			$result = true; 
 		}
 		else
 		{
-			$result = $this->mailer->sendEmail($email['mail_recipient_email'], $email['mail_recipient_name'], $mailToSend, TRUE);	
+			$result = $this->mailer->sendEmail($email['mail_recipient_email'], $email['mail_recipient_name'], $mailToSend, TRUE);
 		}
 
 		// Try and send
@@ -890,6 +900,8 @@ class e107MailManager
 			);
 
 
+
+
 		$result = array();
 
 
@@ -911,7 +923,6 @@ class e107MailManager
 		}
 
 
-
 		// Do any substitutions
 		$search = array();
 		$replace = array();
@@ -974,7 +985,16 @@ class e107MailManager
 	//	e107::getAdminLog()->addDebug($title2.print_a($result,true),true);
 	
 		$result['shortcodes']['MAILREF'] = $email['mail_source_id'];
-	
+
+		if($this->debugMode)
+		{
+			echo "<h3>makeEmailBlock() : Incoming</h3>";
+			print_a($email);
+
+			echo "<h3>makeEmailBlock(): Outgoing</h3>";
+			print_a($result);
+		}
+
 		return $result;
 	}
 
@@ -1716,25 +1736,24 @@ class e107MailManager
 											 'mail_recipient_email' => $row['user_email']
 											 );	
  *						....and other data as appropriate
- *	@param boolean|array $extra - any additional parameters to be passed to the mailer - as accepted by arraySet method.
+ *	@param boolean|array $options - any additional parameters to be passed to the mailer - as accepted by arraySet method.
  *			These parameters will override any defaults, and any set in the template
- *	if ($extra['mail_force_queue'] is TRUE, the mail will be added to the queue regardless of the number of recipients
+ *	if ($options['mail_force_queue'] is TRUE, the mail will be added to the queue regardless of the number of recipients
  *
  *	@return boolean TRUE if either added to queue, or sent, successfully (does NOT indicate receipt). FALSE on any error
  *		(Note that with a small number of recipients FALSE indicates that one or more emails weren't sent - some may have been sent successfully)
  */
 
-	public function sendEmails($templateName, $emailData, $recipientData, $extra = FALSE)
+	public function sendEmails($templateName, $emailData, $recipientData, $options = false)
 	{
 		$log = e107::getAdminLog();
 		$log->addDebug(print_r($emailData, true),true);
 		$log->addDebug(print_r($recipientData, true),true);
 		$log->toFile('mail_manager','Mail Manager Log', true);
-		
-		
+
 		if (!is_array($emailData)) 
 		{
-			return FALSE;
+			return false;
 		}
 		
 		if (!is_array($recipientData))
@@ -1749,23 +1768,14 @@ class e107MailManager
 			$templateName = varset($emailData['mail_send_style'], 'textonly');		// Safest default if nothing specified
 		}
 
-
 		$templateName = trim($templateName);
-		if ($templateName == '') return FALSE;
+		if ($templateName == '') return false;
 
-		
-		// Get template data, override email settings as appropriate
-	//	require_once(e_HANDLER.'mail_template_class.php');
-	//	$ourTemplate = new e107MailTemplate();
-	//	if (!$ourTemplate->setNewTemplate($templateName) && empty($emailData['template'])) return FALSE;		// Probably template not found if error
-	//	if (!$ourTemplate->makeEmailBody($emailData['mail_body'], varset($emailData['mail_include_images'], TRUE))) return FALSE;		// Create body text
-	
-	
-	
-//		$emailData['mail_body_templated'] 	= $ourTemplate->mainBodyText;
 		$this->currentMailBody 				= $emailData['mail_body'];			// In case we send immediately
-//		$emailData['mail_body_alt'] 		= $ourTemplate->altBodyText;
 		$this->currentTextBody 				= strip_tags($emailData['mail_body']);
+
+		//		$emailData['mail_body_templated'] 	= $ourTemplate->mainBodyText;
+		//		$emailData['mail_body_alt'] 		= $ourTemplate->altBodyText;
 		
 		if (!isset($emailData['mail_overrides']))
 		{
@@ -1783,16 +1793,11 @@ class e107MailManager
 			}
 		}
 		
-		
-	
-	
-		$forceQueue = FALSE;
-		
-		
-		if (is_array($extra) && isset($extra['mail_force_queue']))
+
+		if (is_array($options) && isset($options['mail_force_queue']))
 		{
-			$forceQueue = $extra['mail_force_queue'];
-			unset($extra['mail_force_queue']);
+			$forceQueue = $options['mail_force_queue'];
+			unset($options['mail_force_queue']);
 		}
 
 		if($this->debugMode)
@@ -1809,7 +1814,7 @@ class e107MailManager
 			if ($this->mailer == NULL)
 			{
 				e107_require_once(e_HANDLER.'mail.php');
-				$this->mailer = new e107Email($extra);
+				$this->mailer = new e107Email($options);
 			}
 			$tempResult = TRUE;
 			$eCount = 0;
@@ -1833,7 +1838,7 @@ class e107MailManager
 				continue;
 
 		*/
-				if (FALSE == $this->mailer->sendEmail($recip['mail_recipient_email'], $recip['mail_recipient_name'], $mailToSend, true))
+				if (false == $this->mailer->sendEmail($recip['mail_recipient_email'], $recip['mail_recipient_name'], $mailToSend, true))
 				{
 					$tempResult = FALSE;
 					if($this->debugMode)
@@ -1864,7 +1869,7 @@ class e107MailManager
 		// ----------- Too many recipients to send at once - add to the emailing queue ---------------- //
 
 
-		// @TODO - handle any other relevant $extra fields
+		// @TODO - handle any other relevant $options fields
 		$emailData['mail_total_count'] = count($recipientData);
 
 		$result = $this->saveEmail($emailData, TRUE);
diff --git a/e107_handlers/user_handler.php b/e107_handlers/user_handler.php
index 8c4903a1b..e4010f871 100644
--- a/e107_handlers/user_handler.php
+++ b/e107_handlers/user_handler.php
@@ -157,7 +157,7 @@ class UserHandler
 	 *
 	 *	@return string|boolean - FALSE if invalid emcoding method, else encoded password to store in DB
 	 */
-	public function HashPassword($password, $login_name, $force='')
+	public function HashPassword($password, $login_name='', $force='')
 	{
 	  if ($force == '') $force = $this->preferred;
 	  switch ($force)
@@ -207,6 +207,42 @@ class UserHandler
 	}
 
 
+	/**
+	 * Reset the user's password with an auto-generated string.
+	 * @param $uid
+	 * @param string $loginName (optional)
+	 * @return bool|string rawPassword
+	 */
+	public function resetPassword($uid, $loginName='')
+	{
+		if(empty($uid))
+		{
+			return false;
+		}
+
+		$rawPassword    = $this->generateRandomString('********');
+	//	$sessKey        = e_user_model::randomKey();
+
+		$updateQry = array(
+			'user_password' => $this->HashPassword($rawPassword, $loginName),
+			'WHERE'         => 'user_id = '.intval($uid)." LIMIT 1"
+		);
+
+		if(e107::getDb()->update('user', $updateQry))
+		{
+			return $rawPassword;
+		}
+		else
+		{
+			return false;
+		}
+
+
+
+	}
+
+
+
 	/**
 	 *	Verifies a standard response to a CHAP challenge
 	 *
diff --git a/e107_plugins/login_menu/login_menu_shortcodes.php b/e107_plugins/login_menu/login_menu_shortcodes.php
index b0efe0bc5..8b0fdfbbe 100755
--- a/e107_plugins/login_menu/login_menu_shortcodes.php
+++ b/e107_plugins/login_menu/login_menu_shortcodes.php
@@ -42,6 +42,7 @@ global $tp;
 			private $use_imagecode =0;
 			private $sec;
 			private $usernameLabel = LOGIN_MENU_L1;
+			private $allowEmailLogin;
 
 			function __construct()
 			{
@@ -50,6 +51,7 @@ global $tp;
 				$this->use_imagecode = e107::getConfig()->get('logcode');
 				$this->sec = e107::getSecureImg();
 				$this->usernameLabel = '';
+				$this->allowEmailLogin = $pref['allowEmailLogin'];
 
 				if($pref['allowEmailLogin']==1)
 				{
@@ -66,7 +68,11 @@ global $tp;
 			function sc_lm_username_input($parm='')
 			{
 				$pref = e107::getPref();
-				return "<input class='form-control tbox login user' type='text' name='username' placeholder='".$this->usernameLabel."' required='required' id='username' size='15' value='' maxlength='".varset($pref['loginname_maxlength'],30)."' />\n";
+
+				// If logging in with email address - ignore pref and increase to 100 chars.
+				$maxLength  = ($this->allowEmailLogin == 1 || $this->allowEmailLogin) ? 100 : varset($pref['loginname_maxlength'],30);
+
+				return "<input class='form-control tbox login user' type='text' name='username' placeholder='".$this->usernameLabel."' required='required' id='username' size='15' value='' maxlength='".$maxLength."' />\n";
 			}
 
 
diff --git a/fpw.php b/fpw.php
index f81a1cae3..ca1a51d3c 100644
--- a/fpw.php
+++ b/fpw.php
@@ -319,8 +319,15 @@ if (isset($_POST['pwsubmit']))
 		$do_log['user_loginname'] 	= $row['user_loginname'];
 		$do_log['activation_code'] 	= $rcode;
 
+		if(getperms('0'))
+		{
+			$ns->tablerender("Testing Mode", print_a($message,true));
+			require_once(FOOTERF);
+			exit;
+		}
+
 		// Try to send the email 
-		if(sendemail($_POST['email'], "".LAN_09."".SITENAME, $message))
+		if(sendemail($clean_email, "".LAN_09."".SITENAME, $message))
 		{
 			e107::getMessage()->addInfo(LAN_FPW6);
 			$do_log['password_result'] = LAN_FPW20;
diff --git a/signup.php b/signup.php
index d4601c142..edec5e360 100644
--- a/signup.php
+++ b/signup.php
@@ -103,17 +103,24 @@ if ((USER || (intval($pref['user_reg']) !== 1) || (vartrue($pref['auth_method'],
 class signup
 {
 
+	private $testMode = false;
+
 	function __construct()
 	{
 		$pref = e107::pref('core');
 
+		if(getperms('0'))
+		{
+			$this->testMode = true;
+		}
+
 
 		if(substr(e_QUERY,0,9)=='activate.')
 		{
 			$this->processActivationLink();
 		}
 
-		if((e_QUERY == 'resend') && (!USER || getperms('0')) && ($pref['user_reg_veri'] == 1))
+		if((e_QUERY == 'resend') && (!USER || $this->testMode) && ($pref['user_reg_veri'] == 1))
 		{
 			if(empty($_POST['submit_resend']))
 			{
@@ -125,7 +132,7 @@ class signup
 			}
 		}
 
-		if(getperms('0'))
+		if($this->testMode == true)
 		{
 			if(e_QUERY == 'preview')
 			{
@@ -210,28 +217,53 @@ class signup
 		}
 
 		// Now send the email - got some valid info
-		$row['user_password'] = 'xxxxxxx';		// Don't know the real one
-		$eml = render_email($row);
+		$editPassword = e107::getPref('signup_option_password', 2);
+
+		if(empty($editPassword)) // user input of password was disabled, so generate a new one.
+		{
+			$row['user_password'] = $userMethods->resetPassword($row['user_id']);
+		}
+		else
+		{
+			$row['user_password'] = 'xxxxxxx';		// Don't know the real one
+		}
+
+		$row['activation_url'] = SITEURL."signup.php?activate.".$row['user_id'].".".$row['user_sess'];
+
+		$eml = $this->render_email($row);
 		$eml['e107_header'] = $row['user_id'];
 
-		require_once(e_HANDLER.'mail.php');
-		$mailer = new e107Email();
 
-		if(!$mailer->sendEmail(USEREMAIL, USERNAME, $eml, FALSE))
-
-		$do_log['signup_action'] = LAN_SIGNUP_63;
-
-		if(!sendemail($row['user_email'], $eml['subject'], $eml['message'], $row['user_name'], "", "", $eml['attachments'], $eml['cc'], $eml['bcc'], $returnpath, $returnreceipt, $eml['inline-images']))
+		if($this->testMode == true) // Test Mode.
 		{
-			$ns->tablerender(LAN_ERROR,LAN_SIGNUP_42);
+			echo e107::getEmail()->preview($eml);
+
+			e107::getMessage()->setTitle(LAN_SIGNUP_43,E_MESSAGE_SUCCESS)->addSuccess(LAN_SIGNUP_44." ".$row['user_email']." - ".LAN_SIGNUP_45);
+			$ns->tablerender(null,e107::getMessage()->render());
+
+			e107::getMessage()->setTitle(LAN_ERROR,E_MESSAGE_ERROR)->addError(LAN_SIGNUP_42);
+			$ns->tablerender(null, e107::getMessage()->render());
+
+			return true;
+		}
+
+		$result = e107::getEmail()->sendEmail($row['user_email'], $row['user_name'], $eml, false);
+
+		if(!$result)
+		{
+			e107::getMessage()->setTitle(LAN_SIGNUP_43,E_MESSAGE_ERROR)->addError(LAN_SIGNUP_42);
+			$ns->tablerender(null, e107::getMessage()->render());
 			$do_log['signup_result'] = LAN_SIGNUP_62;
 		}
 		else
 		{
-			$ns->tablerender(LAN_SIGNUP_43,LAN_SIGNUP_44." ".$row['user_email']." - ".LAN_SIGNUP_45."<br /><br />");
+			e107::getMessage()->setTitle(LAN_ERROR,E_MESSAGE_SUCCESS)->addSuccess(LAN_SIGNUP_44." ".$row['user_email']." - ".LAN_SIGNUP_45);
+			$ns->tablerender(null,e107::getMessage()->render());
 			$do_log['signup_result'] = LAN_SIGNUP_61;
 		}
+
 		// Now log this (log will ignore if its disabled)
+		$do_log['signup_action'] = LAN_SIGNUP_63;
 
 		e107::getLog()->user_audit(USER_AUDIT_PW_RES,$do_log,$row['user_id'],$row['user_name']);
 
@@ -292,7 +324,7 @@ class signup
 	private function sendEmailPreview()
 	{
 		$temp = array();
-		$eml = render_email($temp, TRUE); // It ignores the data, anyway
+		$eml = $this->render_email($temp, TRUE); // It ignores the data, anyway
 		$mailer = e107::getEmail();
 
 		if(!$mailer->sendEmail(USEREMAIL, USERNAME, $eml, FALSE))
@@ -313,7 +345,7 @@ class signup
 		$tp = e107::getParser();
 
 		$temp = array();
-		$eml = render_email($temp, true); // It ignores the data, anyway
+		$eml = $this->render_email($temp, true); // It ignores the data, anyway
 		$ns->tablerender('Email Preview', $tp->replaceConstants($eml['preview'],'abs'));
 
 	}
@@ -327,7 +359,7 @@ class signup
 	    $allData['data']['user_email'] = "example@email.com";
 		$allData['data']['user_loginname'] = "user_loginname";
 
-	  	$after_signup = render_after_signup(null);
+	  	$after_signup = $this->render_after_signup(null);
 
 		$ns->tablerender($after_signup['caption'], $after_signup['text']);
 	}
@@ -436,6 +468,81 @@ class signup
 
 
 
+	/**
+	 * Create email to send to user who just registered.
+	 * @param array $userInfo is the array of user-related DB variables
+	 * @return array of data for mailer - field names directly compatible
+	 */
+	function render_email($userInfo, $preview = FALSE)
+	{
+
+		if($preview == TRUE)
+		{
+			$userInfo['user_password'] = "test-password";
+			$userInfo['user_loginname'] = "test-loginname";
+			$userInfo['user_name'] = "test-username";
+			$userInfo['user_email'] = "test-username@email";
+			$userInfo['user_website'] = "www.test-site.com";		// This may not be defined
+			$userInfo['user_id'] = 0;
+			$userInfo['user_sess'] = "1234567890ABCDEFGHIJKLMNOP";
+			$userInfo['activation_url'] = 'http://whereever.to.activate.com/';
+		}
+
+		return  e107::getSystemUser($userInfo['user_id'], false)->renderEmail('signup', $userInfo);
+
+
+	}
+
+
+
+	function render_after_signup($error_message='')
+	{
+
+		$ret = array();
+
+		if(!empty($error_message))
+		{
+			$ret['text'] = "<div class='alert alert-danger'>".$error_message."</b></div>";	// Just display the error message
+			$ret['caption'] = LAN_SIGNUP_99; // Problem Detected
+			return $ret;
+		}
+
+		global $pref, $allData, $adviseLoginName, $tp;
+
+		$srch = array("[sitename]","[email]","{NEWLOGINNAME}","{EMAIL}");
+		$repl = array(SITENAME,"<b>".$allData['data']['user_email']."</b>",$allData['data']['user_loginname'],$allData['data']['user_email']);
+
+		$text = "<div class='alert alert-warning'>";
+
+		if (isset($pref['signup_text_after']) && (strlen($pref['signup_text_after']) > 2))
+		{
+			$text .= str_replace($srch, $repl, $tp->toHTML($pref['signup_text_after'], TRUE, 'parse_sc,defs'))."<br />";
+			// keep str_replace() outside of toHTML to allow for search/replace of dynamic terms within 'defs'.
+		}
+		else
+		{
+			$text .= ($pref['user_reg_veri'] == 2) ?  LAN_SIGNUP_37 : str_replace($srch,$repl, LAN_SIGNUP_72);
+			$text .= "<br /><br />".$adviseLoginName;
+		}
+
+		$text .= "</div>";
+
+		$caption_arr = array();
+		$caption_arr[0] = LAN_SIGNUP_73; // Thank you!  (No Approval).
+		$caption_arr[1] = LAN_SIGNUP_98; // Confirm Email (Email Confirmation)
+		$caption_arr[2] = LAN_SIGNUP_100; // Approval Pending (Admin Approval)
+
+		$caption = $caption_arr[$pref['user_reg_veri']];
+
+		$ret['text']    = $text;
+		$ret['caption'] = $caption;
+
+		return $ret;
+
+	}
+
+
+
 }
 
 	if(e_QUERY && e_QUERY != 'stage1')
@@ -931,76 +1038,4 @@ function headerjs()
 }
 
 
-/**
- * Create email to send to user who just registered.
- * @param array $userInfo is the array of user-related DB variables
- * @return array of data for mailer - field names directly compatible
- */
-function render_email($userInfo, $preview = FALSE)
-{
-
-	if($preview == TRUE)
-	{
-		$userInfo['user_password'] = "test-password";
-		$userInfo['user_loginname'] = "test-loginname";
-		$userInfo['user_name'] = "test-username";
-		$userInfo['user_email'] = "test-username@email";
-		$userInfo['user_website'] = "www.test-site.com";		// This may not be defined
-		$userInfo['user_id'] = 0;
-		$userInfo['user_sess'] = "1234567890ABCDEFGHIJKLMNOP";
-		$userInfo['activation_url'] = 'http://whereever.to.activate.com/';
-	}
-	
-	return  e107::getSystemUser($userInfo['user_id'], false)->renderEmail('signup', $userInfo);
-	
-
-}
-
-
-
-function render_after_signup($error_message='')
-{
-
-	$ret = array();
-
-	if(!empty($error_message))
-	{
-		$ret['text'] = "<div class='alert alert-danger'>".$error_message."</b></div>";	// Just display the error message
-		$ret['caption'] = LAN_SIGNUP_99; // Problem Detected
-		return $ret;
-	}
-
-	global $pref, $allData, $adviseLoginName, $tp;
-
-	$srch = array("[sitename]","[email]","{NEWLOGINNAME}","{EMAIL}");
-	$repl = array(SITENAME,"<b>".$allData['data']['user_email']."</b>",$allData['data']['user_loginname'],$allData['data']['user_email']);
-
-	$text = "<div class='alert alert-warning'>";
-
-	if (isset($pref['signup_text_after']) && (strlen($pref['signup_text_after']) > 2))
-	{
-		$text .= str_replace($srch, $repl, $tp->toHTML($pref['signup_text_after'], TRUE, 'parse_sc,defs'))."<br />";
-		// keep str_replace() outside of toHTML to allow for search/replace of dynamic terms within 'defs'.
-	}
-	else
-	{
-		$text .= ($pref['user_reg_veri'] == 2) ?  LAN_SIGNUP_37 : str_replace($srch,$repl, LAN_SIGNUP_72);
-		$text .= "<br /><br />".$adviseLoginName;
-	}
-
-	$text .= "</div>";
-
-	$caption_arr = array();
-	$caption_arr[0] = LAN_SIGNUP_73; // Thank you!  (No Approval).
-	$caption_arr[1] = LAN_SIGNUP_98; // Confirm Email (Email Confirmation)
-	$caption_arr[2] = LAN_SIGNUP_100; // Approval Pending (Admin Approval)
-
-    $caption = $caption_arr[$pref['user_reg_veri']];
-
-    $ret['text']    = $text;
-    $ret['caption'] = $caption;
-
-	return $ret;
-
-}
-?>
+?>
\ No newline at end of file