Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Mailer] Attaching files with fopen from a remote url occasionally crashes SmtpTransport #45350

Closed
@phtmgt

Description

@phtmgt

Symfony version(s) affected

^5.2

Description

This is a bug I've been trying to track for more than a year now, since it happens only occasionally. In the beginning I thought this was an issue with our SMTP server (you will see why below), but I am finally able to pin it down.

We occasionally send a large number (>200) transactional e-mails containing a PDF that we attach from our cdn:

$email = (new TemplatedEmail())
  ->...

foreach ($pdfUrls as $url) {
  $email->attach(fopen($url, 'r'), $generatedName.'.pdf', 'application/pdf');
}

$this->mailer->send($email);

Out of, say 250, emails we occasionally get a very small percentage (e.g. 4/250) that fail and go to failure transport.

When we inspect the first of the failed messages, we see that attachment->body is false. Apparently, this is the problem. How come ->attach method proceeds forward when fopen returns false?

Now, this is the smaller issue. We can probably solve that by retrying 5 times to get the file with fopen (maybe there is an issue with our CDN, throttling, etc.)

The bigger issue is that this situation apparently crashes the whole SmtpTransport, as we get the following error immediately after:

Email transport "Symfony\Component\Mailer\Transport\Smtp\SmtpTransport" stopped

And it crashes in such a way that it somehow breaks the smtp server connection. The next message in the queue fails as well with Connection timeout. We checked the SMTP server logs (it is our own) and apparently symfony sends unexpected data (e.g., starting a new message w/out properly closing the previous transaction; not really sure, e-mail in general is blackbox for most).

So, the result is the problematic email fails and it also breaks the next one in the queue. We know that because a side issue is that the body => false message fails every time it is retried (normal, as the message in the queue holds the same data). I don't think the message should go to the queue at all with attachment->body->false, while the next in queue, which initially failed, works fine on retry.

Any thoughts or suggestions?

How to reproduce

Try sending a large number (>300) e-mails with attachments from an external link with fopen();

Possible Solution

Don't just set attachment body to false, give a meaningful error where the failure occurred.

Additional Context

...
          -isDirty: false
          #collection: Doctrine\Common\Collections\ArrayCollection^ {
            -elements: []
          }
          #initialized: false
        }
        -photo: null
      },
      "content" => "concrete content",
      "notificationAddonBusiness" => "bla bla",
      "notificationAddonCompany" => """
        bla bla
        """
    ]
    -text: "bla bla bla"
    -textCharset: "utf-8"
    -html: null
    -htmlCharset: null
    -attachments: [
      [
        "body" => false,
        "name" => "9000004479.pdf",
        "content-type" => "application/pdf",
        "inline" => false
      ]
    ]
...

See how attachment body is false.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions