Skip to content
This repository has been archived by the owner on Nov 17, 2021. It is now read-only.

Multipart message is build up incorrectly #775

Closed
bztsrc opened this issue Jul 7, 2016 · 3 comments
Closed

Multipart message is build up incorrectly #775

bztsrc opened this issue Jul 7, 2016 · 3 comments

Comments

@bztsrc
Copy link

bztsrc commented Jul 7, 2016

I've noticed that multipart messages are handled wrong. The children are added as they should, but when the message is built, an extra, unwanted level is added, wonder why?

Here's a simple code to reproduce the error:

//create alternatives for the text part
$part1 = Swift_MimePart::newInstance()->setChildren([
    new Swift_MimePart($text, 'text/plain', 'utf-8'),
    new Swift_MimePart($html, 'text/html', 'utf-8')
]);

//build the message
$message = Swift_Message::newInstance($subject, null, 'multipart/mixed')
    ->setFrom(['do-not-reply@test.com' => 'Test'])
    ->setTo(['zoltan.baldaszti@test.com' => 'Zoltan Baldaszti'])
    ->attach($part1, 'multipart/alternative')
    ->attach(new Swift_MimePart($vcal, 'text/calendar'))
    ->attach(Swift_Attachment::newInstance($vcal, 'invite.ics', 'application/ics'));

//dump children recursively (correct, as expected)
function dumpMsg($m, $l=0) {
    echo(str_repeat("\t", $l).$m->getContentType()."\n");
    foreach($m->getChildren() as $a) {
        dumpMsg($a, $l+1);
    }
}
dumpMsg($message);

//output the whole mime message (incorrect, has two alternative blocks)
print_r($message->toString());

/*outputs:
multipart/mixed
    multipart/alternative
        text/plain
        text/html
    text/calendar
    application/ics

Message-ID: <b861c3e5c379c7ea88e497feb309a301@swift.generated>
Date: Thu, 07 Jul 2016 11:24:17 +0100
Subject: Testing
From: Test <do-not-reply@test.com>
To: Zoltan Baldaszti <zoltan.baldaszti@test.com>
MIME-Version: 1.0
Content-Type: multipart/mixed;
 boundary="_=_swift_v4_1467887057_e41b38039433d18a198be902c6319c1a_=_"


--_=_swift_v4_1467887057_e41b38039433d18a198be902c6319c1a_=_
Content-Type: multipart/alternative;
 boundary="_=_swift_v4_1467887057_c4b0e68c1c571bf698a5738e5b7dc42c_=_"


--_=_swift_v4_1467887057_c4b0e68c1c571bf698a5738e5b7dc42c_=_
Content-Type: multipart/alternative;
 boundary="_=_swift_v4_1467887057_8675a1cbc6bb8134bc60d4500d5b1722_=_"


--_=_swift_v4_1467887057_8675a1cbc6bb8134bc60d4500d5b1722_=_
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

One event

--_=_swift_v4_1467887057_8675a1cbc6bb8134bc60d4500d5b1722_=_
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

<html><body>One event</body></html>

--_=_swift_v4_1467887057_8675a1cbc6bb8134bc60d4500d5b1722_=_--


--_=_swift_v4_1467887057_c4b0e68c1c571bf698a5738e5b7dc42c_=_
Content-Type: text/calendar; charset=utf-8
Content-Transfer-Encoding: quoted-printable

VCAL

--_=_swift_v4_1467887057_c4b0e68c1c571bf698a5738e5b7dc42c_=_--


--_=_swift_v4_1467887057_e41b38039433d18a198be902c6319c1a_=_
Content-Type: application/ics; name=invite.ics
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=invite.ics

VkNBTA==

--_=_swift_v4_1467887057_e41b38039433d18a198be902c6319c1a_=_--
*/
@bztsrc
Copy link
Author

bztsrc commented Jul 7, 2016

I think the problem is in Swift_Mime_SimpleMimeEntity::setChildren(), so this could relate to #744 .
By changing the line 337 in swiftmailer/lib/Swift/Mime/SimpleMimeEntity.php to:

$this->_children = $immediateChildren; //$children;

and the dumpMsg() code above will output:

/*
multipart/mixed
    multipart/alternative
        multipart/alternative
            text/plain
            text/html
        text/calendar
    application/ics
*/

Which is incorrect, and the same as how the whole mime message look like. Also, the method setChildren() has a comment in it:

// TODO: Try to refactor this logic

Googling that revealed issue #434 which has a possible solution.

@bztsrc
Copy link
Author

bztsrc commented Jul 10, 2016

A simple workaround to this problem is to introduce a new method for setting childrens:

diff SimpleMimeEntity.old.php SimpleMimeEntity.new.php 
341a342,358
>      * Set all children of this entity without modification.
>      *
>      * @param Swift_Mime_MimeEntity[] $children
>      *
>      * @return Swift_Mime_SimpleMimeEntity
>      */
>     public function setMimeParts(array $children)
>     {
>         $this->_immediateChildren = $children;
>         $this->_children = $children;
>         $this->_fixHeaders();
>         $this->_sortChildren();
> 
>         return $this;
>     }
> 
>     /**

This will keep backward compatibility (no existing project would broke), no redesign required, yet people who want to build complex massages or keep the ordering of attachments would be able to do so by creating MimeParts in advance and adding them to the Message at once with this.

What do you think?

@fabpot
Copy link
Member

fabpot commented Mar 2, 2019

I'm closing this issue as it's going to be fixed by Symfony Mailer/Mime, which will replace Swiftmailer eventually.

@fabpot fabpot closed this as completed Mar 2, 2019
fabpot added a commit to symfony/symfony that referenced this issue Mar 2, 2019
This PR was merged into the 4.3-dev branch.

Discussion
----------

Mime messages

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | many on Swiftmailer
| License       | MIT
| Doc PR        | upcoming

As announced today at SymfonyLive Lille, here is the new MIME component.

This PR is one step towards the new Symfony Mailer (announced at Symfony London). It started as a fork of Swiftmailer, but soon enough I rewrote almost everything to make it (hopefully) better and more flexible. I've removed all the complexity of Swiftmailer when it comes to multiparts for instance.

Some big differences with Swiftmailer:

* Way less complexity (no crazy dependency injection when not needed, less interfaces, no cache)
* Plain data object and no state (out are the observers for charset and encoding, in are POPO and serializable objects)
* No magic regarding multipart management, but a nice wrapper for the most common use cases
  swiftmailer/swiftmailer#434
  swiftmailer/swiftmailer#775
  swiftmailer/swiftmailer#946
  swiftmailer/swiftmailer#615
  swiftmailer/swiftmailer#184
  swiftmailer/swiftmailer#56
  and probably many others
* More Symfony-like
* Messages are built on-demand and we do not mess up with your headers/body (Swiftmailer add headers and change yours, but here, we generate needed headers when converting the message as a string, they are not stored -- it means for instance that generating an Email twice will give you 2 different Date headers)
* and probably more that I don't remember right now

I've also kept some nice features from Swiftmailer like support for any charset.

More information on the slides:

https://speakerdeck.com/fabpot/2-new-symfony-components-httpclient-and-mime

Commits
-------

ee787d1 [Mime] added classes for generating MIME messages
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants