Configuration:
Joomla 4.2.9, PHP 8.1.16, VirtueMart 4.0.13 10799, VMuikit X - 10.27, YOOtheme 3.0.27
When a customer wishes to create their account via the Virtuemart form, the creation is done correctly in the backend, but the problem comes from the generated emails.
- The shop receives this email:
----
User account details of {NAME} at {SITENAME}
Good morning,
A new user '{NAME}', username '{USERNAME}', has registered at {SITEURL}.
so no information about the new client
----
- The customer receives this email
----
User account details of {NAME} at {SITENAME}
Hello {NAME},
Thank you for registering on {SITENAME}. Your account is created and must be activated before it can be used.
To activate the account, select the following link or copy/paste it into your browser:
{ACTIVATE}
After its activation, you will be able to login to {SITEURL} using the following username and password you entered when registering:
Username: {USERNAME}
----
therefore no possibility for the customer to activate his account !!!
From the site administration
the customer is registered but it is up to the administrator to validate it and inform him manually by email that his registration is active
------
Ps:
This bug is present on 4 different websites same configuration and 4 different servers, I also cleaned the FR Joomla 4 language pack by removing all duplicate files with fr-FR.
I also informed JoomlaPro (VmUikit) of this bug which answered me:
We checked with default Virtuemart without our plugin overrides and found that its not worked.
We suspect that the issue was related to virtuemart only.
PS2:
PS: if you use the native Joomla 4 form, the emails are sent correctly and all the fields:
{NAME}, {SITENAME}, {USERNAME}, {ACTIVATE}, {SITEURL} are populated correctly.
Its also happening to us (J4.2.9, VM 4.0.12)
Also here when used the J4 reg form, the relevant fields/tags gets filled correctly.
I'm curious if noone else face this behavior, what could it be!
Same here!
J 4.2.9 / VM 4.0.12 / PHP 8.0.26 (migrated from J3/VM3 to J4/VM4)
Did anyone find a solution to this?
For now the only solution I have found is to deactivate the activation of the account. Do not send the link for activation.
Still no solution for this bug that is losing a lot of customers!!!
What's weird reading the forums is that they had the same problem with "HikaShop" but they fixed it very quickly with the updates...
QuoteStill no solution for this bug that is losing a lot of customers!!!
Oh man :))))
Who used activation for shop user????
If customer want something buy, then shop have to don't use email with activation link, shop have to create silent registration.
Pls change your setup
Hello Pinochico,
I don't quite understand your answer, I've been using Virtuemart since Joomla 1.5 on several of my sites and activation for shop users has always worked great.
Language:
Joomla 3: COM_USERS_EMAIL_REGISTERED_NOTIFICATION_TO_ADMIN_BODY - Hello Administrator,
A new user '%s', username '%s', has registered on %s.
Joomla 4: COM_USERS_EMAIL_REGISTERED_NOTIFICATION_TO_ADMIN_BODY - Hello, \n\nA new user '{NAME}', username '{USERNAME}', has registered at {SITEURL}.
The bug appeared since version 4 of joomla + PHP8
Of course customers can still buy without registering as a "Guest".
But professionals prefer to register and receive the activation link for security
(if this function is useless, why does it exist?)
Especially since the registration works perfectly in Backend
the problem comes only on the sending of the email via Virtuemart
Registration is very useful for customer follow-up, the separation of Professional customers and Individuals (because certain products are only reserved for professionals).
And also in Marketing with ACYMailing.
And if I put
Activation of accounts: on "None" instead of "Auto activation"
the administrator always receives
User account details of {NAME} at {SITENAME}
With {NAME} and {SITENAME} tags empty
@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.
Okay, jenkinhill,
so can you explain to me how to disable this in Joomla and/or Virtuemart ?
A "Solution" suggested for those stores that do require all shoppers to be registered is to force the initial registration through Joomla by turning off the Redirect Joomla to VirtueMart registration in the "VM Framework Loader during Plugin Updates" plugin (yes, an entirely logical plugin name!).
You can use menus to set VM pages to display only to registered users - ie login to view the store - or edit the checkout pages to tell shoppers to login before starting the checkout process. Those who have not yet registered within VM will be asked for billing address info.
Registering in Joomla first ensures that the new registration to admin email includes the member details.
I have a number of Wholesaler websites under construction that requires registration before being able to shop.
The 'solutions' in this thread are only workarounds. A solution to the errors would be appreciated.
Is the error with Joomla4 or VM.???
Registration works just fine with Joomla 3.10.11, including admin confirmation. The same VM code does not work with Joomla 4.x
Does anyone know when Virtuemart will come up to speed with JOOMLA4.???
Very frustrating.!!!
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 !!
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...
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.
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.
Many thanks.!
It would be great to see a permanent solution to this issue.!
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.
Many thanks.!! Works fine.!!!!
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?
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