zendframework/zend-mail

message cloning and headers

basz opened this issue · 5 comments

basz commented
  • I was not able to find an open or closed issue matching what I'm seeing.
  • This is not a question. (Questions should be asked on chat (Signup here) or our forums.)

I have a service that has an injected default message. It has some default fields, such as encoding, from_name, from which are equal for any mail sent.

Internally it will create a clone from the default message and then it will add the actual rendered content, to subject. etc. It also adds Content-Type and an X-Header.

However at some point I noticed messages were having duplicate Content-Type and X-Header headers and some servers will deny those messages. Every time a message is sent and additional header is added. (this is a long running process)

Code to reproduce the issue

        $defaultMessage = new \Zend\Mail\Message();
        $defaultMessage->setFrom('its@me.com');

        $message1 = clone $defaultMessage;
        $message1->getHeaders()->addHeaderLine('X-Something', 1);

        $message2 = clone $defaultMessage;
        $message2->getHeaders()->addHeaderLine('X-Something', 2);

        print $message1->toString();
        print $message2->toString();

Expected results

Headers should be unique due to the clone of the default message

Date: Thu, 14 Jun 2018 08:53:20 +0000
From: its@me.com
X-Something: 1

Date: Thu, 14 Jun 2018 08:53:20 +0000
From: its@me.com
X-Something: 2

Actual results

Date: Thu, 14 Jun 2018 08:53:20 +0000
From: its@me.com
X-Something: 1
X-Something: 2

Date: Thu, 14 Jun 2018 08:53:20 +0000
From: its@me.com
X-Something: 1
X-Something: 2

I'm aware normally one should create a new Message for each Message you attempt to sent. I have changed my code to do this, but I still think this should simply work. I'm wondering why clone doesn't really clone...

basz commented

ps. I'm on php72 and am using 2.10.0 of zend-mail (2.9 also had this)

i've added in my project wrapper which implements __clone:

https://github.com/eventum/eventum/blob/v3.5.1/src/Mail/MailMessage.php#L651-L659

however it still doesn't work, so more deeper __clone() methods needed: eventum/eventum#364

probably need deeper clone in AddressList type headers, which have the address values as objects.

however, doing it properly would mean add __clone() in all objects themselves, not doing top level cloning.

basz commented

I am under the impression that if you do not specify a __clone method a deep clone was performed by default?

rather opposite:

http://php.net/manual/en/language.oop5.cloning.php

When an object is cloned, PHP 5 will perform a shallow copy of all of the object's properties. Any properties that are references to other variables will remain references.

and as objects are always references in php5+, the result is that cloned subobjects remain shared.

This repository has been closed and moved to laminas/laminas-mail; a new issue has been opened at laminas/laminas-mail#28.