7

I am using Magento 1.9.1.0 .

In the backend I set up four different recipients to receive sales copy email every time a customer makes an order. The problem is that every recipient I inserted in the backend receive the same copy email multiple time.

Anyone has experienced this problem before?

  • Do you use the standard mailer ($mailer = new Zend_Mail('utf-8'); $mailer->send();) or are you using SMTP or via a 3rd party module? – tecjam Mar 5 '15 at 16:26
  • And how is your cron configured? If it runs in too short a time apart, it could be that you have multiple instances run at the same time. – tecjam Mar 5 '15 at 16:30
  • I am using the standard mailer, no SMTP or third party module. I am using "aeo scheduler" and it is configured to run core_email_queue_send_all every minute. – gianis6 Mar 5 '15 at 16:55
  • I tried to change the scheduling time of core_email_queue_send_all, setting it to six minutes but the result is still the same. – gianis6 Mar 5 '15 at 17:25
  • 1
    I can't provide an answer, but wanted to confirm experiencing the issue. The customer got 1 e-mail, the first e-mail in the configuration got 2, the second got 3 etc. The issue is resolved, but I'm not sure what if anything my colleague did to fix it. – Peter O'Callaghan Mar 6 '15 at 9:04
4

TL;DR: use the "Bcc" option instead of the "Separate Email" option for order copy emails, because the latter is seriously broken in Magento 1.9.1. It will expose your copy email addresses to the customer.

There is something fundamentally broken with how Magento is handling this. When you have multiple (comma-separated) email addresses specified in "Send Order Email Copy To" with "Send Order Email Copy Method" set to "Separate Email", Magento creates multiple separate messages in the core_email_queue table - one for the customer and one for each Copy recipient.

(example: set to copy to test@example.com, foobar@example.com)

message_id    entity_id    entity_type    event_type    message_body_hash
4             19           order          new_order     b0faf3b948557fc38cf1ef564d0db16e
5             19           order          new_order     b0faf3b948557fc38cf1ef564d0db16e
6             19           order          new_order     b0faf3b948557fc38cf1ef564d0db16e

That is fine - it has created separate messages for each recipient.

However the actual recipients are stored in another table - core_email_queue_recipients. This is where the problem is. Instead of assigning one recipient to each message, this is what happens:

recipient_id    message_id    recipient_email
13              4             foobar@example.com
14              5             foobar@example.com
15              5             test@example.com
16              6             foobar@example.com
17              6             test@example.com
18              6             customer@example.com

it assigns 1 recipient to the first message, 2 to the second, 3 to the third etc. The more recipients you have added to the Copy field, the more emails the last email on that list will receive.

What should have been added to core_email_queue_recipients is this:

recipient_id    message_id    recipient_email
13              4             foobar@example.com
14              5             test@example.com
15              6             customer@example.com

What is worse is that the emails are no longer "separate" because the email sent to the customer will have included in the "To" field a list of all the other email addresses (which should have been sent separately and without knowledge of the customer) - thus exposing to the customer your entire copy list.

Fixing this issue requires overriding and substantially rewriting the broken copy logic in Mage/Sales/Model/Order::queueNewOrderEmail() as well as Mage/Core/Model/Email/Queue, which isn't trivial to do.

A short term fix is simply to change the copy method from "Separate Email" to "Bcc" - this option works as expected and will only generate one email.

1

Magento compares queue entries from database and clears recipients only if results found.

In my case the message_body_hash was different because Magento uses a global variable ($taxIter) in tax/order/tax.phtml, which increments each time this template is called.

<tr class="summary-details-1 summary-details summary-details-first">

Just try to add this line to your local.xml

    <sales_email_order_items>
    <reference name="order_totals">
        <reference name="tax">
            <action method="setTemplate"><template>tax/order/tax-email.phtml</template></action>
        </reference>
    </reference>
</sales_email_order_items>

And copy template "tax/order/tax.phtml" to "tax/order/tax-email.phtml" and change :

...
global $taxIter; $taxIter++;
...

to:

...
$taxIter=0; $taxIter++;
...

Otherwise try to understand the process I've tried to explain and hopefully find the difference.

Magento is queueing two messages in "core_email_queue" if your configuration for "Send Order Email Copy Method" is set to "Separate Email". The first mail is for specified recipients in backend. The second mail will receive your customer.

The messages will be saved in Mage_Core_Model_Email_Template#send().

public function send($email, $name = null, array $variables = array())
{
    if (!$this->isValidForSend()) {
        Mage::logException(new Exception('This letter cannot be sent.')); // translation is intentionally omitted
        return false;
    }

    $emails = array_values((array)$email);
    $names = is_array($name) ? $name : (array)$name;
    $names = array_values($names);
    foreach ($emails as $key => $email) {
        if (!isset($names[$key])) {
            $names[$key] = substr($email, 0, strpos($email, '@'));
        }
    }

    $variables['email'] = reset($emails);
    $variables['name'] = reset($names);

    $this->setUseAbsoluteLinks(true);
    $text = $this->getProcessedTemplate($variables, true);
    $subject = $this->getProcessedTemplateSubject($variables);

    $setReturnPath = Mage::getStoreConfig(self::XML_PATH_SENDING_SET_RETURN_PATH);
    switch ($setReturnPath) {
        case 1:
            $returnPathEmail = $this->getSenderEmail();
            break;
        case 2:
            $returnPathEmail = Mage::getStoreConfig(self::XML_PATH_SENDING_RETURN_PATH_EMAIL);
            break;
        default:
            $returnPathEmail = null;
            break;
    }

    if ($this->hasQueue() && $this->getQueue() instanceof Mage_Core_Model_Email_Queue) {
        /** @var $emailQueue Mage_Core_Model_Email_Queue */
        $emailQueue = $this->getQueue();
        $emailQueue->setMessageBody($text);
        $emailQueue->setMessageParameters(array(
                'subject'           => $subject,
                'return_path_email' => $returnPathEmail,
                'is_plain'          => $this->isPlain(),
                'from_email'        => $this->getSenderEmail(),
                'from_name'         => $this->getSenderName(),
                'reply_to'          => $this->getMail()->getReplyTo(),
                'return_to'         => $this->getMail()->getReturnPath(),
            ))
            ->addRecipients($emails, $names, Mage_Core_Model_Email_Queue::EMAIL_TYPE_TO)
            ->addRecipients($this->_bccEmails, array(), Mage_Core_Model_Email_Queue::EMAIL_TYPE_BCC);
        $emailQueue->addMessageToQueue();

        return true;
    }

    ...
}

This method is triggered twice and proceed with the same queue-model (Mage_Core_Model_Email_Queue $emailQueue) including variables ($_recipients) of first run.

->addRecipients($emails, $names, Mage_Core_Model_Email_Queue::EMAIL_TYPE_TO)

This Line will add customer's email address to existing _recipients array.

 $emailQueue->addMessageToQueue();

Magento is trying to save queue model to database and checks if email was already added to queue for requested recipients.

Mage_Core_Model_Resource_Email_Queue#wasEmailQueued

 public function wasEmailQueued(Mage_Core_Model_Email_Queue $queue)
{
    $readAdapter = $this->_getReadAdapter();
    $select = $readAdapter->select()
        ->from(
            array('recips' => $this->getTable('core/email_recipients')),
            array('recipient_email', 'recipient_name', 'email_type')
        )
        ->join(array('queue' => $this->getMainTable()), 'queue.message_id = recips.message_id', array())
        ->where('queue.entity_id =? ', $queue->getEntityId())
        ->where('queue.entity_type =? ', $queue->getEntityType())
        ->where('queue.event_type =? ', $queue->getEventType())
        ->where('queue.message_body_hash =? ', md5($queue->getMessageBody()));

    $existingRecipients = $readAdapter->fetchAll($select);
    if ($existingRecipients) {
        ...
           $queue->clearRecipients();
            foreach ($diff as $recipient) {
                list($email, $name, $type) = $recipient;
                $queue->addRecipients($email, $name, $type);
            }
        ...
    }

    return false;
}

If queue entry in core_email_queue with same data (entity_id, entity_type, event_type and message_body_hash) is found, a method to clear recipients will be called. It took me some time to figure it out.

1

For everyone still suffering this issue, I've been through the same problems with this as @solarissmoke have exposed.

I've written a very simple custom module for fixing this, that is working for me as expected, even with "Separate Email" copy method. You can check it and clone it here: https://github.com/UQPPA/FixSeparateCopyMethod

Problem resides in Mage_Core_Model_Email_Queue being saved (there is when it saves recipients data, @see \Mage_Core_Model_Email_Queue::_afterSave method) multiple times without clearing its recipients through different saves, so when it adds a new recipient, it saves not only current recipients, but also old ones.

0

This issue could be related to the new Magento Email Queue system, that leaves orphan records on the Recipients table.

If this is your issue, I've sent a fix (by adding a foreign key) on this post: https://magento.stackexchange.com/a/87299/23057

0

In our case we are creating order from cron. It means we already have quotes created using api and we ran cron to convert those quotes into order. However 4/10 emails are duplicate . What can be the reason ? I have check the all the configuration We are also using the ao_scheduler and send email cron is runs on every minute is this the culprit ? I mean is it can be possible multiple process running same time ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.