How to Get All Orders of a Customer by Email in Magento 2 (Complete Guide)

How to Get All Orders of Customer by Email ID in Magento 2

Want to fetch all Magento 2 orders for a customer using their email? You can do it reliably by filtering orders on customer_email using either the recommended OrderRepository + SearchCriteria approach, or a quick Order Collection filter.

This is useful for support teams, admin custom reports, CRM integrations, loyalty workflows (discount codes for repeat buyers), or exporting order history based on an email address.

Important: An email may belong to a registered customer or a guest checkout. In Magento, orders store the email in sales_order.customer_email for both cases, so the same filter works either way.

How Magento 2 stores orders by email

Magento saves the order email on each order record (table: sales_order) under the field customer_email. That means you can retrieve:

  • Registered customer orders (email matches their customer account email)
  • Guest orders (email entered at checkout, no customer account required)

Recommended: Get customer orders by email using OrderRepository (best practice)

This approach is cleaner for service classes, APIs, and maintainable modules. It also makes pagination and filtering easier.

Example: Create a model/service class (not a Block) and fetch orders using SearchCriteria.

<?php
declare(strict_types=1);

namespace Vendor\Module\Model;

use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Sales\Api\Data\OrderInterface;

class OrderByEmail
{
    private OrderRepositoryInterface $orderRepository;
    private SearchCriteriaBuilder $searchCriteriaBuilder;

    public function __construct(
        OrderRepositoryInterface $orderRepository,
        SearchCriteriaBuilder $searchCriteriaBuilder
    ) {
        $this->orderRepository = $orderRepository;
        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
    }

    /**
     * Get orders by customer/guest email.
     *
     * @param string $email
     * @param int $pageSize
     * @param int $currentPage
     * @return OrderInterface[]
     */
    public function getOrdersByEmail(string $email, int $pageSize = 20, int $currentPage = 1): array
    {
        $searchCriteria = $this->searchCriteriaBuilder
            ->addFilter('customer_email', $email)
            ->setPageSize($pageSize)
            ->setCurrentPage($currentPage)
            ->create();

        $result = $this->orderRepository->getList($searchCriteria);
        return $result->getItems();
    }
}

Optional filters (status, store, date range)

In real stores, you usually want to filter further to improve performance and avoid mixing orders across stores.

// Add these before ->create()

->addFilter('status', ['complete','processing'], 'in')     // filter by order status
->addFilter('store_id', 1)                                 // single store
->addFilter('created_at', '2026-01-01 00:00:00', 'gteq')    // date from

Quick method: Get order collection by email (fast and simple)

If you just need a quick internal use case (custom script, admin widget, simple report), the order collection approach works well.

<?php
declare(strict_types=1);

namespace Vendor\Module\Model;

use Magento\Sales\Model\ResourceModel\Order\CollectionFactory;
use Magento\Sales\Model\ResourceModel\Order\Collection;

class OrderCollectionByEmail
{
    private CollectionFactory $orderCollectionFactory;

    public function __construct(CollectionFactory $orderCollectionFactory)
    {
        $this->orderCollectionFactory = $orderCollectionFactory;
    }

    /**
     * @param string $email
     * @return Collection
     */
    public function getOrderCollectionByEmail(string $email): Collection
    {
        $collection = $this->orderCollectionFactory->create();
        $collection->addFieldToFilter('customer_email', $email);

        // Optional: sort newest first + limit results
        $collection->setOrder('created_at', 'DESC');
        $collection->setPageSize(50);

        return $collection;
    }
}

How to output order details (email, phone, totals, items)

Once you have the orders, you can loop and extract commonly needed fields. Keep it minimal and safe (avoid exposing PII publicly).

foreach ($orders as $order) {
    $incrementId = $order->getIncrementId();
    $createdAt   = $order->getCreatedAt();
    $email       = $order->getCustomerEmail();
    $phone       = $order->getBillingAddress() ? $order->getBillingAddress()->getTelephone() : '';
    $grandTotal  = $order->getGrandTotal();

    // Items count
    $qty = 0;
    foreach ($order->getAllVisibleItems() as $item) {
        $qty += (int)$item->getQtyOrdered();
    }
}

Common issues (and fixes)

  • No results: confirm the email matches exactly (case sensitivity can matter in some setups) and check guest orders.
  • Too many results / slow query: add filters (status/store/date) and pagination.
  • Wrong layer: avoid doing this logic in a Block; use a Model/Service class so it’s reusable and testable.
  • Security: don’t expose order history by email in a public endpoint without authentication.

When should you use this in real projects?

This pattern is commonly used in:

  • Customer support tools (lookup order by email)
  • Admin dashboards and custom reports
  • Loyalty logic (reward repeat buyers)
  • Integrations (CRM, ERP, accounting exports)

If you want this implemented as a clean Magento 2 admin report, API endpoint, or automated loyalty workflow (with safe access controls), you can hire a Magento developer from our team here:

Hire Magento Developer

Quick question: Do you want this to return only registered customer orders, only guest orders, or both? (Both is the default and most common.)

Talk to a Hyvä expert
Loading...