Hi Andrew You can create a new php file.
Let's call it customer.php and place it on the same level as index.php file af Magento. Put this code in the file.
error_reporting(E_ALL | E_STRICT); $mageFilename = 'app/Mage.php'; if (!file_exists($mageFilename)) { if (is_dir('downloader')) { header("Location: downloader"); } else { echo $mageFilename." was not found"; } exit; } require_once $mageFilename; Varien_Profiler::enable(); Mage::setIsDeveloperMode(true); ini_set('display_errors', 1); umask(0); Mage::app('default'); $passwordLength = 10; $customers = Mage::getModel('customer/customer')->getCollection(); foreach ($customers as $customer){ //[Update 2012-04-19: thanks Michael] $customer->load($customer->getId()); //[/Update 2012-04-19] $customer->setPassword($customer->generatePassword($passwordLength))->save(); $customer->sendNewAccountEmail(); } ?>
then just call the page in your browser http://mydomain.com/customer.php After you finish delete the customer.php file from your server to avoid running it again.
Can you limit the selection to users without passwords? I imported users without passwords and I want to assign them to those users, but not users with passwords.
ReplyDeleteYes you can. Just replace this:
ReplyDelete$customers = Mage::getModel('customer/customer')->getCollection();
with this
$customers = Mage::getModel('customer/customer')->getCollection()->addAttributeToFilter(array(array('attribute'=>'password_hash', 'eq'=>'')));
I'm wondering if you can import customer login and hashed password, I believe Magento uses MD5 encryption I still can't find the code needed to correctly import customers. Also what if the customer is in a different customer group?
ReplyDeleteFor the customer group I have a solution.
ReplyDeleteIn the script above inside the foreach you can add before calling $customer->save(), this:
$customer->setGroupId('YOUR GROUP ID HERE').
For your first problem, importing the hashed passwords I don't have a solution.
You can try instead of setPassword to use setPasswordHash, but I'm not sure it will work. I don't know (yet) how the password salt works in Magento.
I had one small problem with this, if you leave the template as is, using the magento calls for urls, i.e. the call thats in the new customer email template that links them to login, (/customer/login) then it links relative to where the script was origionally called. so my login link inside of my email was mydomain.com/my_resetscript.php/customer/login
ReplyDeleteWe have a database of 3400 customers, and after about 100 users clicked it immediately (I forgot to remove the script right away) it sent out a total of somewhere near 60,000+ emails, and froze our server. It also upset a lot of customers, so if you are going to do this, take precautions. This is just a warning.
Hello. I get this error when using the code on Magento 1.4.1.1. Any ideas would be appreciated.
ReplyDeleteFatal error: Uncaught exception 'Mage_Core_Model_Store_Exception' in /home/magento/app/code/core/Mage/Core/Model/App.php:1247 Stack trace: #0 /home/magento/app/code/core/Mage/Core/Model/App.php(760): Mage_Core_Model_App->throwStoreException() #1 /home/magento/app/Mage.php(322): Mage_Core_Model_App->getStore(NULL) #2 /home/magento/app/Mage.php(334): Mage::getStoreConfig('web/url/use_sto...', NULL) #3 /home/magento/app/code/core/Mage/Core/Controller/Request/Http.php(204): Mage::getStoreConfigFlag('web/url/use_sto...') #4 /home/magento/app/code/core/Mage/Core/Controller/Request/Http.php(156): Mage_Core_Controller_Request_Http->_canBeStoreCodeInUrl() #5 /home/magento/app/code/core/Mage/Core/Model/App.php(379): Mage_Core_Controller_Request_Http->setPathInfo() #6 /home/magento/app/code/core/Mage/Core/Model/App.php(262): Mage_Core_Model_App->_initRequest() #7 /home/magento/app/Mage.php(570): Mage_Core_Model_App->init('default', 'store', Array) #8 /home/magento/gen_pass.php(17): Mage::app('default') #9 {main} thrown in /home/magento/app/code/core/Mage/Core/Model/App.php on line 1247
Hello Aydin. I never got this error before, but I think there is a problem with your store code. You don't have a store with the code 'default'. If this is the case replace 'default' with one of your store codes in 'Mage::app('default');'.
ReplyDeleteHello tzyganu,
ReplyDeleteYes, changing the store code resolved the problem. Thanks for your help and the great script.
Hi, great post but just wondering would this would work on a very large store?
ReplyDeleteOur store has over 13000 customers that we have just migrated from creLoaded.
Will this work for so many or will it just error or is there a way to process the emails in batches to ensure success?
Hello Ryan.
ReplyDeleteIn theory it should work for any number of customers. But the time needed to finish is going to be long.
My recommendation is to split them in batches.
In order to add a filter to the collection replace this
$customers = Mage::getModel('customer/customer')->getCollection();
with this
$customers = Mage::getModel('customer/customer')->getCollection()->addAttributeToFilter('entity_id', array('gte'=>$startId))->addAttributeToFilter('entity_id',array('lt'=>$endId));
'gte' means greater then or equal
'lt' means less then.
You can addapt the script to receive 2 parameters $startId and $endId and run it from the command line on separate threads.
Cheers,
Marius.
This script works really well. The only problem I have is that the customer’s name does not display properly in the email. I’ve tried several different variations of the customer name variable in my transactional template (and yes, the template is enabled and configured). The default is {{htmlescape var=$customer.name}}. When I send individual password generation emails from the Magento backend they display the customer name just fine using the default {{htmlescape var=$customer.name}}.
ReplyDeleteDo I need to pass an argument to sendNewAccountEmail()?
Thanks for any help on this!
Hello Michael.
DeleteWhat do you mean by 'customer’s name does not display properly'. Give me an example.
This shouldn't happen, because the script uses the same methods as the 'create account' process.
Then again I wrote this 2 and half years ago, maybe something has changed. :).
Marius.
Marius, thank you for the quick reply.
DeleteWhat I mean is that sendNewAccountEmail() sends the New account email template. My transactional template for this email (which is based on the default and was only changed to include my store logo) has a subject = "Welcome, {{var customer.name}}!" and a first line of "Dear {{htmlescape var=$customer.name}},"
This works fine when users register and displays the full customer name. However, when I use your script those two variables both are blank. So the subejct is "Welcome, !" and the first line says "Dear ,".
I hope this clarified my question and thank you again for your diligence!
Marius, just wondering if you saw my reply clarifying your question...
DeleteYes I saw it.
DeleteSorry for answering with a delay. Please take into consideration the timezone difference. I'm on GMT + 2.
It seams that not all the attributes for the customer are loaded when looping through the collection.
The solution is to add this line: $customer->load($customer->getId()); as the first line inside the foreach loop. I updated the post to fit your needs.
Cheers,
Marius.
Marius, no worries about the timing. I know Magento devs are all over the world. I only got concerned because your first reply was so quick!
ReplyDeleteThank you for taking the time to go back over this after so long. Magnificent job, it now works perfectly!
Again, I really appreciate your diligence! Thank you again!
Yeah...my fist response was quick because you caught me just before "shutdown".
DeleteGlad I could help.
Marius.
I'm trying to use your script to send passwords in batches. I just added $customers = Mage::getModel('customer/customer')->getCollection()->addAttributeToFilter('entity_id', array(1=>$startId))->addAttributeToFilter('entity_id',array(50=>$endId)); to the script. I'm getting this error Fatal error: Uncaught exception 'Exception' with message 'Notice: Undefined variable: startId in /var/www/clients/client1/web1/web/customer.php on line 19' in /var/www/clients/client1/web1/web/app/code/core/Mage/Core/functions.php:245Stack trace: #0 /var/www/clients/client1/web1/web/customer.php(19): mageCoreErrorHandler(8, 'Undefined varia...', '/var/www/client...', 19, Array) #1 {main} thrown in /var/www/clients/client1/web1/web/app/code/core/Mage/Core/functions.php on line 245
ReplyDeletetry it like this:
Delete$startId = 1;
$endId = 50;
customers = Mage::getModel('customer/customer')->getCollection()->addAttributeToFilter('entity_id', array('gte'=>$startId))->addAttributeToFilter('entity_id',array('lt'=>$endId));
I had to uncomment the line Mage::setIsDeveloperMode(true); to get it to work. I would otherwise throw a fatal error. (version 1.6.2)
ReplyDeleteWhet error did you get?
DeleteThank you for the post. I would like to use this but I have a little issue. Is there a way this will reset the password of the customers who have not reset their password or never logged in magento. We migrated customers from Oscommerce and many customers have already reset their passwords or are new customers. I want to reset only users who have not logged into magento yet. Appreciate the help. Thanks
ReplyDeleteHello Magentist.
DeleteI'm not sure this will work but you can try it.
There is a field in the customer table (customer_entity) called 'updated_at'. This is the last date and hour any customer data was updated (captain obvious).
You can try to reset the password only for customers that have this field lower that a specific date (date of the migration + 5 minutes for example).
I think you can do that by replacing in the script this:
$customers = Mage::getModel('customer/customer')->getCollection();
with this:
$somedate = YOUR DATE VALUE HERE (for example: 2012-11-11 12:35:00)
$customers = Mage::getModel('customer/customer')->getCollection()
->addAttributeToFilter('updated_at', array('gte'=>$somedate));
Don't try it directly on live. Try it first on a backup db and don't send out emails.
Let me know if it works.
If in your previous website (Oscommerce) you didn't have this field it's even easier. The updated_at field should be blank (0000-00-00 00:00:00) or will have the same value for all the customers (the date of the migration). But this depends on the way the migration was done.
Cheers.
Marius.
Thank you Marius, you are awesome. I will try it out and let you know if it worked.
ReplyDeleteThanks tzyganu!
ReplyDeleteI can confirm that still working for magento 1.7.0.2
But don't work your patch for only send to customers without passwords, the second comment in this post.
$customers = Mage::getModel('customer/customer')->getCollection();
with this
$customers = Mage::getModel('customer/customer')->getCollection()->addAttributeToFilter(array(array('attribute'=>'password_hash', 'eq'=>'')));
When I change the file, is not sending any e-mail how if all customers have a password.
I was imported the customer using the default magento import tool.
Can you help me with this?
thanks!
hey,
ReplyDeleteWhen i run the code i get this fatal error.
Fatal error: Uncaught exception 'Exception' with message 'Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 8: parser error : StartTag: invalid element name in /home/senorehe/public_html/lib/Varien/Simplexml/Config.php on line 510' in /home/senorehe/public_html/app/code/core/Mage/Core/functions.php:245 Stack trace: #0 [internal function]: mageCoreErrorHandler(2, 'simplexml_load_...', '/home/senorehe/...', 510, Array) #1 /home/senorehe/public_html/lib/Varien/Simplexml/Config.php(510): simplexml_load_string('loadFile('/home/senorehe/...') #4 /home/senorehe/public_html/app/code/core/Mage/Core/Model/Config.php(315): Mage_Core_Model_Config->_loadDeclaredModules() # in /home/senorehe/public_html/app/code/core/Mage/Core/functions.php on line 245
any chance you know why?
Most probably this has nothing do to with the code in the post. I think that one of the files in app/etc/modules is not properly formatted.
Deleteif i want to send reset password mail to all customer what changes have i to made for it ??
ReplyDeleteNothing. That's what the small script does.
Deletehow do i send a custom transactional email i created using the template "New Account" to the affected group users instead of the default email?
ReplyDeleteAny updates need to be made to this for 1.9?
ReplyDeleteI haven't tested this on 1.9 but it should work without any issues. The internal API did not change regarding to customer passwords.
DeleteHello, i have installed the script with 777 privilegies, but i have error 404. What im doing wrong?
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteFor anybody who arrives here and needs to email only customers who don't have a password and/or have never been sent an email with this code.
ReplyDeleteFirst a quick note, for whatever reason, you are unable to check whether the password_hash is null or ''. I tried so many variations and am pretty sure it just fails to filter this for some reason. You can however, check if the password_hash already exists. Secondly, my php and Magento skills are nonexistent, so feel free to make this code more efficient.
To use this code, you must create a custom attribute for customers called initemail and set it as a boolean (Yes/No) with default as No.
getCollection()
//Check for accounts
->addAttributeToFilter(array(array('attribute'=>'password_hash', 'neq'=>'')));
foreach ($customers as $customer){
$customer->load($customer->getId());
//Update custom field to true
$customer->setinitemail(1)->save();
};
//Email based on custom field
$customers1 = Mage::getModel('customer/customer')->getCollection()
->addAttributeToFilter(
array(
array('attribute'=>'initemail','0'),
array('attribute'=>'initemail',array('null'=>true))
));
//Original code + custom field update
foreach ($customers1 as $cust){
//[Update 2012-04-19: thanks Michael]
$cust->load($cust->getId());
//[/Update 2012-04-19]
$cust->setPassword($cust->generatePassword($passwordLength))->save();
$cust->sendNewAccountEmail();
$cust->setinitemail(1)->save();
}
?>