Export email addresses to CSV in Magento

This cropped up the other day – the client wanted to export all customer email addresses from their Magento store for all historical orders, not just those of registered customers. The information was to be imported into Mailchimp, so needed to be dumped into a CSV file containing the customer’s first name, last name and email address.

Updated

Note that this script wasn’t working on all installations – this has now been fixed with the addition of two lines at the start of the script.

The below script is the quick and dirty solution. Nothing massively complicated about it, it does exactly what it says on the tin, and if called through the browser (beware timeouts for larger stores) or over the command line, it creates a CSV called file.csv stored in the same directory on the server as the script, which contains the relevant information in it.

Here’s the code – enjoy!

<?php
require_once("app/Mage.php");
Mage::app();
Mage::app()->getStore()->setId(Mage_Core_Model_App::ADMIN_STORE_ID);
$orders = Mage::getModel('sales/order')->getCollection();
$orders->setPage(1, 3000);
$fp = fopen('file.csv', 'w');
foreach($orders as $order) {
	$fields = array($order->getBillingAddress()->getFirstname(),$order->getBillingAddress()->getLastname(),$order->getBillingAddress()->getEmail());
	fputcsv($fp, $fields);
}
?>

59 comments

  • Mimmo

    Thank you, Giles!
    I have HTTP ERROR 500

    Why? I have Magento 1.9.2.4

    • Giles Bennett (author)

      You’ve done something wrong, I imagine – 500 means a server error. Turn on error reporting in your script by adding :


      ini_set('display_errors', 1);

      to the top of it.

  • a

    THANK YOU!

  • Steve

    Hi,
    Forgive what may be a daft question.

    What’s the relevance of the setPage(1, 3000)?

    We have a store with 94129 (approx) orders and we want to use a this method to list the last 3000.

    Obviously prefer not to set the script going on the full 94129 as I would imagine that could take a while!

    Thanks in advance.
    Steve

    • Giles Bennett (author)

      Steve,

      It just means it starts at the first result in the collection and runs through the first 3000. Adjust accordingly to pull out the last 3000 (ie. starting at X-3000 where X is the total number of orders).

      Kind regards,

      Giles

  • Steve Sproston

    Hi Giles,

    I’ve come to the party late here but found your snippet and almost found it perfect for my needs – to output Order number, Email, First & Last name.

    When I run it, I get the array count incrementing by 1 each time but it’s only sequentially counting the orders rather than giving the true order number from the store (there are some order numbers missing due to abandoned orders, etc).

    Is it possible to also load the order number to the csv file?

    Thanks
    Steve

    • Giles Bennett (author)

      Steve,

      $order->getId() should get the Magento ID, and $order->getIncrementId() would get the “nice” order number (that the customer sees). Add either of those to the array of fields being exported accordingly.

      Kind regards,

      Giles

  • Piers

    Hi Giles,

    Thanks for this. Just to let you know we needed to change the email request to the following to get it to work:

    $order->getCustomerEmail()

    Thanks again,
    Piers

    • Giles Bennett (author)

      Piers,

      Thanks – the original post is about three years old now, so may well be at the mercy of variations in later versions of Magento.

      Kind regards,

      Giles

  • Nick

    Cheers Giles

    Any pointers on making that export between dates?

    • Giles (author)

      Nick,

      You want to filter the order collection to orders placed between the dates in question, rather than just loading all orders. This post has an example of filtering an order collection which should get you going.

      Kind regards,

      Giles

  • Kevin

    Thank you so much! It works great.
    You help a lot of people with this, including me !

    • Giles (author)

      Kevin,

      You’re welcome!

      Kind regards,

      Giles

  • Ghulam Ali

    hey Giles thank for the export script. can you please share import orders script. thanks

    • Giles (author)

      Ali,

      If you have a particular script you need written then get in touch over email – giles@hummingbirduk.com.

      Kind regards,

      Giles

  • André

    Hi,

    Is it possible to add an from to date field for customers?

    • Giles (author)

      André,

      Yes, you can add “$order->getDate()” to the array.

      Kind regards,

      Giles

  • jeffrey

    Hello Giles,

    No sure if this was addressed, but could it be done for customers based off of SKU? So only customers that ordered a particular SKU would be exported. Thanks

    • Giles (author)

      Jeff,

      You would have to add to the script to loop through each order in turn, get all items from the order, loop through all the items and their SKUs and only write to the CSV where the relevant SKU is present in the order.

      Kind regards,

      Giles

  • Martin

    Hi Giles

    Will this script only look for emails in orders with status “Completed”? Our magento setup stores also orders which have not been completed and i don’t really want those peoples e-mails.

    • Giles (author)

      Martin,

      It will pull out all orders which have been put through the system, whether they’ve been paid, are awaiting payment, have been dispatched or not. It won’t pull through “quotes”, ie baskets for customers who haven’t yet gone through the checkout process.

      Kind regards,

      Giles

      • Martin

        Awesome, thanks :o)

  • Christian Rasmussen

    Thank you so much. It works perfectly in 1.7.0.2 and 1.9.1
    Just look for the file.csv on the FTP 🙂

    Best regards Christian

  • Rad

    How and where do i place this code?

    • Giles (author)

      In a file in the web root of your Magento installation, using FTP. If any of those things don’t mean much to you, you might want to consider hiring a developer to do it for you!

  • Steve

    What if we have over 150,000 orders? Would this script cause our server to time out?

    • Giles (author)

      Depends on your PHP settings, but if you ran it from the command line, probably not, no.

  • Adam

    Great script, just wondering if you could put a store Id in there rather than exporting all customers, just export them from a particular store?

    thanks

    Adam

    • Giles (author)

      Adam,

      Have you tried changing :

      Mage::app()->getStore()->setId(Mage_Core_Model_App::ADMIN_STORE_ID);
      

      to set the ID of the specific store you want?

      Kind regards,

      Giles

      • taylor

        Firstly thanks for this bit of code it’s pretty helpful.
        I’m running into some problems isolating a single store though
        Using that line of code above how can I export only from one store? I Tried changing it to setID(1) to try and only export from store ID 1 but it still shot them all out. As well I tried the long key from Manage Stores in place of the ID but it gave me the same result.

        • Giles (author)

          Taylor,

          Presuming you know the store ID in question, you would want to remove the line :

          Mage::app()->getStore()->setId(Mage_Core_Model_App::ADMIN_STORE_ID);
          

          and change the following line to :

          $orders = Mage::getModel('sales/order')->getCollection()->addFieldToFilter('store_id', 1);
          

          Kind regards,

          Giles

          • taylor

            Thank you it worked like a charm

  • Heny

    Hey thank you so much for your open source contribution. It worked here on 1.7, thanks again!

  • Brian

    Neat hack. Not sure if it still works for 1.8. I get this output when it runs.

    Great! The file uploaded properly. Now click the ‘Verify my file’ button to complete the process.

    • Giles (author)

      Brian,

      Not sure precisely what you’re doing to generate that content – from what I can tell from a quick Google search, that seems to be the content from the Alexa verification file?

      The script has been tested on 1.8 and works fine – you should be uploading it via FTP to, say, script.php, then visiting http://www.yoursite.com/script.php in your browser.

      Kind regards,

      Giles

  • MMedia

    Hi Giles,

    Thanks for taking the time to write this post, however I copied your file, ran it from the root and I just get a blank page?

    Magento 1.7.0.2.

    • Giles (author)

      Yes – the script doesn’t output anything to the screen on completion (it’s very quick and dirty) but if you look in the same directory that you put the PHP file in, you should now see a newly created file called “file.csv” with the relevant information in it. It writes the file to the server, rather than offer it up as a download.

      Giles

      • MMedia

        That’s what you get for skim reading a post, you’re right and it works a treat.

        Awesome, thank you very much!

        Ed

        • Giles (author)

          Ed,

          No problem, glad you found it useful.

          Giles

  • Kosta

    I did successful run the script but it only export the names of the customers.
    Please advice me how to get emails and all the atributes of each order.
    Thank you.

    • Kosta

      Hey Giles,

      I found the reason for empty field of email.
      the field “$order->getBillingAddress()->getEmail()” everytime is NULL

      Do you have any suggestions.

      Thank you.

      • Giles (author)

        I’m not entirely sure why…I’ve just downloaded the file and run it on a site and it’s exported names and emails with no problem whatsoever. What version of Magento are you running?

        Giles

      • daihlo

        I get the same things. exports first and last name but nothing for email!
        1.7.0.2

        • Giles (author)

          Maybe try changing

          $order->getBillingAddress()->getEmail()
          

          to

          $order->getCustomerEmail()
          

          Does that have an impact?

          Giles

  • eric

    I could not get this to work for the life of me. it is exactly what i am looking for!! i put the code into email_address.php dumped that onto my
    public and tried to run from the browser no luck??? any other suggestions. I created a file.csv to see if that was the issue? changed permissions to 777 nada tostada.

    • Giles (author)

      Eric,

      I’ve double checked the code – cut and pasted the example straight into a new file and it’s working fine. The only thing I can think is that the link to app/Mage.php in the first line may not be correct if you didn’t put the email_address.php file in the web root of your site? Feel free to drop me an email (giles@hummingbirduk.com) if you want me to take a look.

      Kind regards,

      Giles

  • inverse_square

    Great script! Thanks!

    But is there a possibility to export more than those information? e.g. the order id, status of order?
    i guess it’s just about adding variables… but i don’t know those specific ones… where can i find them?

    • Giles (author)

      Yes – just add more sections into the

      	$fields = array($order->getBillingAddress()->getFirstname(),$order->getBillingAddress()->getLastname(),$order->getBillingAddress()->getEmail());
      

      line of the script. So to export the Order ID and the current status you’d want to change that line to :

      	$fields = array($order->getId(), $order->getStatus(), $order->getBillingAddress()->getFirstname(),$order->getBillingAddress()->getLastname(),$order->getBillingAddress()->getEmail());
      

      Hope that helps.

      Giles

      • inverse_square

        Thank you, Giles!

        Can you tell me… How do i know the name of the sections i want to export? Are those identifiers in magento listed? (i hope you know what i mean)

        greets.

        • Giles (author)

          Well, the information is being loaded through the Order model in the third line :

          $orders = Mage::getModel('sales/order')->getCollection();
          

          and we’re then looping through each order with this :

          foreach($orders as $order) {
             Do stuff
          }
          

          We could load all that order’s information – so use :

          $thisOrder = $order->getData();
          

          Which would populate $thisOrder with an array containing contains all of the order information. Then output that information with :

          print_r($thisOrder);
          

          and it’ll show all the sections, along with the relevant information for that order. You can then use that as a guide to be more specific in just getting the sections that you want.

          Don’t just print_r($thisOrder) for every order in the collection, though, as it’ll be massive waste of resources. Modify the script first to just iterate through the loop once, rather than through every order, and print out that single order’s information. Then use that to get the section names and data for each order.

          Hope that helps.

  • Katelyn

    I’m sorry I’m a newbie. Where do I place this code? Do I create a file, say called emails.php, upload it to the server, then navigate to it and it will run?

    • Giles (author)

      Katelyn,

      Yep, that’s about the sum of it. If it’s in the main directory of your Magento installation, it’ll run just fine. If you put it anywhere else, you’ll just have to tweak the first line (require_once(“app/Mage.php”);) as that’s pointing to a specific file in your app directory (Mage.php) that the script needs to link into Magento – if the file’s anywhere other than the main directory of your installation, then it won’t be able to find it, so won’t run properly.

      Hope that helps,

      Giles

      • Katelyn

        Awesome, thank you Giles!

        • Giles (author)

          You’re welcome!

      • Jerel

        It’s three years later and this code has just saved me massive amounts of time. Thank you so much!!

        • Giles Bennett (author)

          You’re welcome.

          Kind regards,

          Giles

  • sean

    what file permission do you use for this file?

    • Giles (author)

      Sean,

      It was only on the server for the time it takes to run it, then was deleted immediately afterwards, so whatever works for you – I don’t think 777 is particularly risky given that it’s just there for a short time.

      Giles

Leave a Reply

Your email address will not be published. Required fields are marked *

Want to talk to us about your project?