News:

You may pay someone to create your store, or you visit our seminar and become a professional yourself with the silver certification

Main Menu

Registration email bug

Started by multistud, March 23, 2023, 17:08:58 PM

Previous topic - Next topic

tramber91

Hi all

Same issue also on my side (Joomla 4.2.9 VM 4.0.12 PHP 8.0 & 8.1)
When Using Joomla registration, in activation mail link, tag are display.
No Tag with Virtuemart registration in activation mail link, only the {ACTIVATE}.

Frustration on my side too !!
joomla 3.9.25 -    php 7.3 - VirtueMart 3.8.8

jjk

I just did test the registration email with Joomla 4.3.0. Basically it works, except that the user email is filled with placeholders.
The registration email sent to the user is coming from a Joomla language keys/string. For example this one:

COM_USERS_EMAIL_REGISTERED_WITH_ADMIN_ACTIVATION_BODY
Hello {NAME},\n\nThank you for registering at {SITENAME}. Your account is created and must
be verified before you can use it.\n\nTo verify the account select the following link or copy-
paste it in your browser:\n{ACTIVATE} \n\nAfter verification an administrator will be notified
to activate your account. You'll receive a confirmation when it's done.\n\nOnce that account
has been activated you may login to {SITEURL} using the following username and
password:\n\nUsername: {USERNAME}\nPassword: {PASSWORD_CLEAR}

So the question is why the Joomla user model sends an email without including the data?

This needs further investigation...
Non-English Shops: Are your language files up to date?
http://virtuemart.net/community/translations

jjk

Joomla has changed the method used to fill the variables in language files.

Sticking with my example posted above yesterday, the previously used language key/string was:

COM_USERS_EMAIL_REGISTERED_WITH_ADMIN_ACTIVATION_BODY="Hello %s,\n\nThank you for registering at %s. Your account is created and must be verified before you can use it.\nTo verify the account select the following link or copy-paste it in your browser:\n %s \n\nAfter verification an administrator will be notified to activate your account. You'll receive a confirmation when it's done.\nOnce that account has been activated you may login to %s using the following username and password:\n\nUsername: %s\nPassword: %s"

As a temporary workaround you can create a new language override in Joomla for your site language using this old language string with %s for the variable placeholders.

I just tested this successfully.
Non-English Shops: Are your language files up to date?
http://virtuemart.net/community/translations

Jumbo!

Quote from: jjk on April 19, 2023, 23:56:47 PM
So the question is why the Joomla user model sends an email without including the data?

It is not the Joomla user model, but the VirtueMart user model which is not settings the email template variables correctly for Joomla 4. We need to update the codes in VirtueMart's user model for Joomla 4. I will share the codes soon.

dudley389

Many thanks.!
It would be great to see a permanent solution to this issue.!

Jumbo!

#20
Here is the solution.

We have to update the VirtueMartModelUser::register() function to fix the issue.

First, backup this file - administrator/components/com_virtuemart/models/user.php.

Now open in a text/code editor - administrator/components/com_virtuemart/models/user.php

Find the following codes between lines 277 to 551. The line numbers may vary depending on the VirtueMart version.

public function register($user, $new) {

$params = JComponentHelper::getParams('com_users');

$useractivation = $params->get('useractivation');
$sendpassword = $params->get('sendpassword', 1);

VmLanguage::loadJLang('com_users',1);
// Load the users plugin group.
JPluginHelper::importPlugin('user');

// Store the data.
if (!$user->save())
{
vmError(JText::sprintf('COM_USERS_REGISTRATION_SAVE_FAILED', $user->getError()));
return false;
} else if( !$new ){
return true;
}

$config = JFactory::getConfig();
$db = JFactory::getDbo();
$query = $db->getQuery(true);

// Compile the notification mail values.
$data = $user->getProperties();
$data['fromname'] = $config->get('fromname');
$data['mailfrom'] = $config->get('mailfrom');
$data['sitename'] = $config->get('sitename');
$data['siteurl'] = JUri::root();

// Handle account activation/confirmation emails.
if ($useractivation == 2)
{
// Set the link to confirm the user email.
$linkMode = $config->get('force_ssl', 0) == 2 ? Route::TLS_FORCE : Route::TLS_IGNORE;

$data['activate'] = JRoute::link(
'site',
'index.php?option=com_users&task=registration.activate&token=' . $data['activation'],
false,
$linkMode,
true
);

$emailSubject = JText::sprintf(
'COM_USERS_EMAIL_ACCOUNT_DETAILS',
$data['name'],
$data['sitename']
);

if ($sendpassword)
{
$emailBody = JText::sprintf(
'COM_USERS_EMAIL_REGISTERED_WITH_ADMIN_ACTIVATION_BODY',
$data['name'],
$data['sitename'],
$data['activate'],
$data['siteurl'],
$data['username'],
$data['password_clear']
);
}
else
{
$emailBody = JText::sprintf(
'COM_USERS_EMAIL_REGISTERED_WITH_ADMIN_ACTIVATION_BODY_NOPW',
$data['name'],
$data['sitename'],
$data['activate'],
$data['siteurl'],
$data['username']
);
}
}
elseif ($useractivation == 1)
{
// Set the link to activate the user account.
$linkMode = $config->get('force_ssl', 0) == 2 ? Route::TLS_FORCE : Route::TLS_IGNORE;

$data['activate'] = JRoute::link(
'site',
'index.php?option=com_users&task=registration.activate&token=' . $data['activation'],
false,
$linkMode,
true
);

$emailSubject = JText::sprintf(
'COM_USERS_EMAIL_ACCOUNT_DETAILS',
$data['name'],
$data['sitename']
);

if ($sendpassword)
{
$emailBody = JText::sprintf(
'COM_USERS_EMAIL_REGISTERED_WITH_ACTIVATION_BODY',
$data['name'],
$data['sitename'],
$data['activate'],
$data['siteurl'],
$data['username'],
$data['password_clear']
);
}
else
{
$emailBody = JText::sprintf(
'COM_USERS_EMAIL_REGISTERED_WITH_ACTIVATION_BODY_NOPW',
$data['name'],
$data['sitename'],
$data['activate'],
$data['siteurl'],
$data['username']
);
}
}
else
{

$pw = '';
if($sendpassword){
$pw = $data['password_clear'];
}

$this->sendRegistrationEmail($user,$pw, $useractivation);
return true;
}

$debug_email = VmConfig::get('debug_mail', false);

// Send the registration email.
if (VmConfig::showDebug() and $debug_email == 'debug_email') {
$msg = 'Registration Debug mail active, no mail sent. The mail to send subject ' . $emailSubject . ' to "' .   $data['email'] . '" from ' . $data['mailfrom'] . ' ' . $data['fromname'] . ' ' . vmText::$language->getTag() . '<br>' . $emailBody;
vmdebug($msg);
$return = true;
} else if(!empty($useractivation)){
$return = JFactory::getMailer()->sendMail($data['mailfrom'], $data['fromname'], $data['email'], $emailSubject, $emailBody);
}


// Send Notification mail to administrators
if (($params->get('useractivation') < 2) && ($params->get('mail_to_admin') == 1))
{
$emailSubject = JText::sprintf(
'COM_USERS_EMAIL_ACCOUNT_DETAILS',
$data['name'],
$data['sitename']
);

$emailBodyAdmin = JText::sprintf(
'COM_USERS_EMAIL_REGISTERED_NOTIFICATION_TO_ADMIN_BODY',
$data['name'],
$data['username'],
$data['siteurl']
);

// Get all admin users
$query->clear()
->select($db->quoteName(array('name', 'email', 'sendEmail')))
->from($db->quoteName('#__users'))
->where($db->quoteName('sendEmail') . ' = 1')
->where($db->quoteName('block') . ' = 0');

$db->setQuery($query);

try
{
$rows = $db->loadObjectList();
}
catch (RuntimeException $e)
{
vmError(JText::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()), 500);

return false;
}



// Send mail to all superadministrators id
foreach ($rows as $row)
{
if (VmConfig::showDebug() and $debug_email == 'debug_email') {
$msg = 'Registration Debug mail to admin active, no mail sent. The mail to send subject ' . $emailSubject . ' to "' .  $row->email . '" from ' . $data['mailfrom'] . ' ' . $data['fromname'] . ' ' . vmText::$language->getTag() . '<br>' . $emailBodyAdmin;
vmdebug($msg);
$return = true;
} else {
$return = JFactory::getMailer()->sendMail($data['mailfrom'], $data['fromname'], $row->email, $emailSubject, $emailBodyAdmin);
}


// Check for an error.
if ($return !== true)
{
vmError(JText::_('COM_USERS_REGISTRATION_ACTIVATION_NOTIFY_SEND_MAIL_FAILED'));

return false;
}
}
}

// Check for an error.
if ($return !== true)
{
vmError(JText::_('COM_USERS_REGISTRATION_SEND_MAIL_FAILED'));

// Send a system message to administrators receiving system mails
$query->clear()
->select($db->quoteName('id'))
->from($db->quoteName('#__users'))
->where($db->quoteName('block') . ' = ' . (int) 0)
->where($db->quoteName('sendEmail') . ' = ' . (int) 1);
$db->setQuery($query);

try
{
$userids = $db->loadColumn();
}
catch (RuntimeException $e)
{
vmError(JText::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()), 500);

return false;
}

if (count($userids) > 0)
{
$jdate = new JDate;

// Build the query to add the messages
foreach ($userids as $userid)
{
$values = array(
$db->quote($userid),
$db->quote($userid),
$db->quote($jdate->toSql()),
$db->quote(JText::_('COM_USERS_MAIL_SEND_FAILURE_SUBJECT')),
$db->quote(JText::sprintf('COM_USERS_MAIL_SEND_FAILURE_BODY', $return, $data['username']))
);
$query->clear()
->insert($db->quoteName('#__messages'))
->columns($db->quoteName(array('user_id_from', 'user_id_to', 'date_time', 'subject', 'message')))
->values(implode(',', $values));
$db->setQuery($query);

try
{
$db->execute();
}
catch (RuntimeException $e)
{
vmError(JText::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()), 500);

return false;
}
}
}

return false;
}

if ($useractivation == 1)
{
return 'useractivate';
}
elseif ($useractivation == 2)
{
return 'adminactivate';
}
else
{
return $user->id;
}
}


Replace the above codes with the following.

public function register($user, $new)
{
$params         = JComponentHelper::getParams('com_users');
$useractivation = $params->get('useractivation');
$sendpassword   = $params->get('sendpassword', 1);

VmLanguage::loadJLang('com_users', 1);
// Load the users plugin group.
JPluginHelper::importPlugin('user');

// Store the data.
if (!$user->save())
{
vmError(JText::sprintf('COM_USERS_REGISTRATION_SAVE_FAILED', $user->getError()));
return false;
}
elseif (!$new)
{
return true;
}

$mailer       = null;
$mailtemplate = 'com_users.registration.user.registration_mail';
$app          = JFactory::getApplication();
$config       = JFactory::getConfig();
$db           = JFactory::getDbo();
$query        = $db->getQuery(true);

// Compile the notification mail values.
$data = $user->getProperties();

$data['fromname'] = $config->get('fromname');
$data['mailfrom'] = $config->get('mailfrom');
$data['sitename'] = $config->get('sitename');
$data['siteurl']  = JUri::root();

// Handle account activation/confirmation emails.
if ($useractivation == 2)
{
// Set the link to confirm the user email.
$linkMode = $config->get('force_ssl', 0) == 2 ? Route::TLS_FORCE : Route::TLS_IGNORE;

$data['activate'] = JRoute::link(
'site',
'index.php?option=com_users&task=registration.activate&token=' . $data['activation'],
false,
$linkMode,
true
);

$emailSubject = JText::sprintf(
'COM_USERS_EMAIL_ACCOUNT_DETAILS',
$data['name'],
$data['sitename']
);

$mailtemplate = 'com_users.registration.user.admin_activation';

if ($sendpassword)
{
$mailtemplate .= '_w_pw';

$emailBody = JText::sprintf(
'COM_USERS_EMAIL_REGISTERED_WITH_ADMIN_ACTIVATION_BODY',
$data['name'],
$data['sitename'],
$data['activate'],
$data['siteurl'],
$data['username'],
$data['password_clear']
);
}
else
{
$emailBody = JText::sprintf(
'COM_USERS_EMAIL_REGISTERED_WITH_ADMIN_ACTIVATION_BODY_NOPW',
$data['name'],
$data['sitename'],
$data['activate'],
$data['siteurl'],
$data['username']
);
}
}
elseif ($useractivation == 1)
{
// Set the link to activate the user account.
$linkMode = $config->get('force_ssl', 0) == 2 ? Route::TLS_FORCE : Route::TLS_IGNORE;

$data['activate'] = JRoute::link(
'site',
'index.php?option=com_users&task=registration.activate&token=' . $data['activation'],
false,
$linkMode,
true
);

$emailSubject = JText::sprintf(
'COM_USERS_EMAIL_ACCOUNT_DETAILS',
$data['name'],
$data['sitename']
);

$mailtemplate = 'com_users.registration.user.self_activation';

if ($sendpassword)
{
$mailtemplate .= '_w_pw';

$emailBody = JText::sprintf(
'COM_USERS_EMAIL_REGISTERED_WITH_ACTIVATION_BODY',
$data['name'],
$data['sitename'],
$data['activate'],
$data['siteurl'],
$data['username'],
$data['password_clear']
);
}
else
{
$emailBody = JText::sprintf(
'COM_USERS_EMAIL_REGISTERED_WITH_ACTIVATION_BODY_NOPW',
$data['name'],
$data['sitename'],
$data['activate'],
$data['siteurl'],
$data['username']
);
}
}
else
{
$pw = '';

if ($sendpassword)
{
$mailtemplate .= '_w_pw';

$pw = $data['password_clear'];
}

if (version_compare(JVERSION, '4.0.0', 'lt'))
{
$this->sendRegistrationEmail($user,$pw, $useractivation);

return true;
}
}

$debug_email = VmConfig::get('debug_mail', false);

// Send the registration email.
if (VmConfig::showDebug() and $debug_email == 'debug_email')
{
$msg = 'Registration Debug mail active, no mail sent. The mail to send subject ' . $emailSubject . ' to "' .   $data['email'] . '" from ' . $data['mailfrom'] . ' ' . $data['fromname'] . ' ' . vmText::$language->getTag() . '<br>' . $emailBody;
vmdebug($msg);
$return = true;
}
else
{
if (version_compare(JVERSION, '4.0.0', 'ge'))
{
$mailer = new \Joomla\CMS\Mail\MailTemplate($mailtemplate, $app->getLanguage()->getTag());

$mailer->addTemplateData($data);
$mailer->addRecipient($data['email']);

$return = $mailer->send();
}
else
{
$return = JFactory::getMailer()->sendMail($data['mailfrom'], $data['fromname'], $data['email'], $emailSubject, $emailBody);
}
}

// Send Notification mail to administrators
if (($params->get('useractivation') < 2) && ($params->get('mail_to_admin') == 1))
{
$emailSubject = JText::sprintf(
'COM_USERS_EMAIL_ACCOUNT_DETAILS',
$data['name'],
$data['sitename']
);

$emailBodyAdmin = JText::sprintf(
'COM_USERS_EMAIL_REGISTERED_NOTIFICATION_TO_ADMIN_BODY',
$data['name'],
$data['username'],
$data['siteurl']
);

// Get all admin users
$query->clear()
->select($db->quoteName(array('name', 'email', 'sendEmail')))
->from($db->quoteName('#__users'))
->where($db->quoteName('sendEmail') . ' = 1')
->where($db->quoteName('block') . ' = 0');

$db->setQuery($query);

try
{
$rows = $db->loadObjectList();
}
catch (RuntimeException $e)
{
vmError(JText::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()), 500);

return false;
}

// Send mail to all superadministrators id
foreach ($rows as $row)
{
if (VmConfig::showDebug() and $debug_email == 'debug_email')
{
$msg = 'Registration Debug mail to admin active, no mail sent. The mail to send subject ' . $emailSubject . ' to "' .  $row->email . '" from ' . $data['mailfrom'] . ' ' . $data['fromname'] . ' ' . vmText::$language->getTag() . '<br>' . $emailBodyAdmin;
vmdebug($msg);
$return = true;
}
else
{
if (version_compare(JVERSION, '4.0.0', 'ge'))
{
$mailer = new \Joomla\CMS\Mail\MailTemplate('com_users.registration.admin.new_notification', $app->getLanguage()->getTag());

$mailer->addTemplateData($data);
$mailer->addRecipient($row->email);

$return = $mailer->send();
}
else
{
$return = JFactory::getMailer()->sendMail($data['mailfrom'], $data['fromname'], $row->email, $emailSubject, $emailBodyAdmin);
}
}

// Check for an error.
if ($return !== true)
{
vmError(JText::_('COM_USERS_REGISTRATION_ACTIVATION_NOTIFY_SEND_MAIL_FAILED'));

return false;
}
}
}

// Check for an error.
if ($return !== true)
{
vmError(JText::_('COM_USERS_REGISTRATION_SEND_MAIL_FAILED'));

// Send a system message to administrators receiving system mails
$query->clear()
->select($db->quoteName('id'))
->from($db->quoteName('#__users'))
->where($db->quoteName('block') . ' = ' . (int) 0)
->where($db->quoteName('sendEmail') . ' = ' . (int) 1);

$db->setQuery($query);

try
{
$userids = $db->loadColumn();
}
catch (RuntimeException $e)
{
vmError(JText::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()), 500);

return false;
}

if (count($userids) > 0)
{
$jdate = new JDate;

// Build the query to add the messages
foreach ($userids as $userid)
{
$values = array(
$db->quote($userid),
$db->quote($userid),
$db->quote($jdate->toSql()),
$db->quote(JText::_('COM_USERS_MAIL_SEND_FAILURE_SUBJECT')),
$db->quote(JText::sprintf('COM_USERS_MAIL_SEND_FAILURE_BODY', $return, $data['username']))
);
$query->clear()
->insert($db->quoteName('#__messages'))
->columns($db->quoteName(array('user_id_from', 'user_id_to', 'date_time', 'subject', 'message')))
->values(implode(',', $values));

$db->setQuery($query);

try
{
$db->execute();
}
catch (RuntimeException $e)
{
vmError(JText::sprintf('COM_USERS_DATABASE_ERROR', $e->getMessage()), 500);

return false;
}
}
}

return false;
}

if ($useractivation == 1)
{
return 'useractivate';
}
elseif ($useractivation == 2)
{
return 'adminactivate';
}
else
{
return $user->id;
}
}


This should resolve the issue. Please test and confirm.

After making the above changes, you also should be able to customise the email layout within Joomla 4 - Mail Templates section.

dudley389

Many thanks.!! Works fine.!!!!

modernmagic

I don't know if it is because of the new code, but the link in the email includes: &Itemid=101

/component/users/?task=registration.activate&token=2a614304009b990aaef9e105ecebddaa&Itemid=101

which just brings the user to the home page.

Wouldn't it be better to bring them to their order history page /orders-list?layout=list OR /checkout IF they clicked this verification link during the process of checking out? 

Is &Itemid=101 what everyone else deals with or is there a better solution?

modernmagic

Quote from: jenkinhill on April 12, 2023, 11:44:25 AM
@pinochico I agree. Asking a shopper to register is a put-off for some customers, but asking them to confirm registration is a guaranteed sales loser.

There will always be some types of stores that require registration in order to confirm age, for example, but as a general rule it's a bad idea. 

As most VM store owners will know, even if a store is set to require confirmation, someone who has just completed the billing info, but has not yet responded to the confirmation email, can complete any purchase in the cart. They become a "registered" shopper in VM but are not registered in Joomla. This may be an unwanted feature by some shop owners but may save orders from being lost.

I have never turned on the sending of new registrations to admins, so have not seen the bug with J4 that has been reported.

Can you please reply to this topic in regards to the best setup for registration?  https://forum.virtuemart.net/index.php?topic=150031.0