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.
$mailer = new Zend_Mail('utf-8'); $mailer->send();
) or are you using SMTP or via a 3rd party module?