mail attachment not included

Created on 28 April 2022, over 2 years ago
Updated 13 April 2023, over 1 year ago

in a commerce2 project I am trying to send emails with invoices and attached pdf of the invoice.
this seems to be covered here:
https://www.drupal.org/project/commerce_invoice/issues/3089861 ๐Ÿ’ฌ Email the customer invoice Fixed
mail pdf is created and the mail get sent, but are missing the attached pdf.

has this patch made it to RC1?

๐Ÿ› Bug report
Status

Closed: won't fix

Component

Code

Created by

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • ๐Ÿ‡ซ๐Ÿ‡ทFrance Toki Caen, Normandy

    @nojj Are you sure it is fixed by the Symfony Mailer dev version?
    Until I have switched from SwiftMailer to Symfony mailer, I can not get Commerce Invoice attaching invoices to emails.
    I am working on Drupal 9.5 (on PHP 8.1) with Commerce invoice 2.0-rc3 and Symfony Mailer 1.x-dev.
    As it worked on drupal test website, I have uninstalled Mail System and SwiftMailer (emails are fine globally).

    Drupal log sent this message (Type : commerce_invoice) :

    RuntimeException: Failed to start the session because headers have already been sent by "/home/my-website/public_html/vendor/symfony/http-foundation/Response.php" at line 1239. in Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage->start() (line 152 of /home/my-website/public_html/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php).

    Thanks for any tip here.

  • Status changed to Active over 1 year ago
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance Toki Caen, Normandy
  • ๐Ÿ‡ธ๐Ÿ‡ฌSingapore vhin0210

    Subscribed. Have the same issue as #9 ๐Ÿ› mail attachment not included Active

  • I use Symfony mailer lite and for it it also doesn't include invoice as attachment on D10.3.1. Any solutions?

  • ๐Ÿ‡ธ๐Ÿ‡ฌSingapore vhin0210

    Found a workaround for this.

    What I did is I override the commerce_invoice.invoice_confirmation_subscriber on my custom module and did this:

    /**
       * {@inheritdoc}
       */
      public function sendInvoiceConfirmation(WorkflowTransitionEvent $event) {
        parent::sendInvoiceConfirmation($event);
    
        $invoice_storage = $this->entityTypeManager->getStorage('commerce_invoice');
        $invoice_type_storage = $this->entityTypeManager->getStorage('commerce_invoice_type');
        /** @var \Drupal\commerce_invoice\Entity\InvoiceInterface[] $invoices */
        $invoices = $invoice_storage->loadMultiple($this->invoicesList);
        foreach ($invoices as $invoice) {
          /** @var \Drupal\commerce_invoice\Entity\InvoiceTypeInterface $invoice_type */
          $invoice_type = $invoice_type_storage->load($invoice->bundle());
          $this->invoiceConfirmationMail->send($invoice, $invoice->getEmail(), $invoice_type->getConfirmationBcc());
        }
      }
    
      /**
       * {@inheritdoc}
       */
      public function destruct() {
        return;
      }
    

    In summary, I moved the send mail logic from destruct() to inside sendInvoiceConfirmation().

    Sending from destruct() somehow triggering the session error.

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia rajivgandhi chinnakrishnan

    #13 is not working as expected. It is sending email twice.

    We are encountering the following error in the backend while attempting to send the invoice confirmation email.

    RuntimeException: Failed to start the session because headers have already been sent by "/var/www/html/vendor/symfony/http-foundation/Response.php" at line 431. in Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage->start() (line 132 of /var/www/html/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php)

    It sends an email to the user. However, the invoice status is marked as "pending" instead of "paid".

    Filename - commerce_invoice/src/Mail/InvoiceConfirmationMail.php
    Line no - 103

    return $this->mailHandler->sendMail($to, $subject, $body, $params);

    If we comment out this line, the invoice status updated correctly, but the email is not sent to the user.

    I am using Drupal 10.3.2.

    Any solutions? Thanks in advance.

  • ๐Ÿ‡ต๐Ÿ‡ญPhilippines erom

    this is a very rough solution... but hopefully it helps while the issue is still being resolved..

  • ๐Ÿ‡ต๐Ÿ‡ญPhilippines erom

    this is an updated patch..

  • ๐Ÿ‡ต๐Ÿ‡ญPhilippines erom
  • ๐Ÿ‡ต๐Ÿ‡ญPhilippines erom

    another approach is do not use this patch and use service modifiers instead.

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia rajivgandhi chinnakrishnan

    #18 what we need to do with service modifiers?

  • ๐Ÿ‡ต๐Ÿ‡ญPhilippines erom

    service modifiers will alter the existing service of commerce invoice and you can implement your own event subscribers to send emails.

  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany netzkombuese

    Hi there.

    We have the same issue here.
    We patched with #15 which attaches the Invoice on prepaid payment gateways. Everything is fine.

    But now when some customer uses Paypal the invoice sending is fired twice.
    One mail with attached invoice and one without.

    I think this is something which is also covered here where this is marked as fixed:

    https://www.drupal.org/project/commerce_invoice/issues/3198668 ๐Ÿ› Order onPaid event called twice RTBC

    This is fixed when we use commerce invoice without the patch in #15 but then the invoice pdf is missing.
    If we install the patch the invoice mal is fired twice again.

    Could this be adjusted?

    Thanks for help

    Jan

  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany netzkombuese

    Hi.

    Here s an updated version ob #17 fixing the above plus some improvements.

    This patch resolves the issue of duplicate invoice emails being sent in the commerce_invoice module, particularly during payment transitions like PayPal. It also ensures that the invoice PDF is correctly attached to the email.

    Key Fixes:

    โ€ข Prevents duplicate emails by introducing a send_email_sent flag, ensuring each invoice email is sent only once.
    โ€ข Moves email sending directly into the markInvoiceForEmailSending() method, improving reliability and avoiding the use of destruct().
    โ€ข Triggers email on specific events, including when an order is marked as pending (for bank transfers) or paid (for PayPal).
    โ€ข Attaches the invoice PDF to the email reliably.

    This patch improves overall email handling and ensures invoices are correctly delivered with their attached PDF, without duplicates.

    For us this is working so fa now :-)

    Thanks

  • Status changed to Needs review 3 months ago
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance Renrhaf ๐Ÿ“ Strasbourg ๐Ÿฆ๐Ÿฆœ

    +1 thanks for the patch, working for us

  • ๐Ÿ‡ช๐Ÿ‡ธSpain henkpotman

    In my web site in Drupal10.2.5 using commerce-invoice 8.x-2.0-rc3 and symfony_mailer 1.4.1 the pdf invoices were attached correctly to the emails.

    Now I updated my web using Composer to Drupal 10.3.5, commerce-invoice 8.x-2.0-rc5 and symfony_mailer 1.5.0.
    After this update, the pdf invoices are not attached to the e-mail anymore. I get the same error message as mentioned by #9:

    RuntimeException: Failed to start the session because headers have already been sent by "/home/my-website/vendor/symfony/http-foundation/Response.php" at line 431. in Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage->start() (line 132 of /home/my-website/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php).

    I have applied the commerce_invoice_no_invoice_duplicate_mail.patch indicated in #22 but now I get following error message:

    Connection to "process /usr/sbin/sendmail -bs" has been closed unexpectedly.

    Is there a problem with the patch as I applied it on version 8.x-2.0-rc5 and not on 8.x-2.0-rc1?
    Or could the symfony_mailer 1.5.0 be the cause of the initial problem after update and should I downgrade back to 1.4.1?

    Or can it have anything to do with the mailer configuration of my website (although it worked before and I didn't change anything?)

    Any comments are welcome!

  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany netzkombuese

    Hi there.
    Just to report back...
    We can confirm that. We also had no problems with 10.2.x. Only after upgrading to 10.3.x the PDF was no longer attached.
    So this really seems to have something to do with changes made in 10.3.x Core.

    I have applied the commerce_invoice_no_invoice_duplicate_mail.patch indicated in #22 but now I get following error message:

    Connection to "process /usr/sbin/sendmail -bs" has been closed unexpectedly.

    Is there a problem with the patch as I applied it on version 8.x-2.0-rc5 and not on 8.x-2.0-rc1?
    Or could the symfony_mailer 1.5.0 be the cause of the initial problem after update and should I downgrade back to 1.4.1?

    Or can it have anything to do with the mailer configuration of my website (although it worked before and I didn't change anything?)

    For me this sounds like a config error with your sendmail path or sednmail config.
    Which module do you use for this?
    In our setup we use https://www.drupal.org/project/symfony_mailer_lite โ†’ without any problems.
    Our sendmail path is /usr/sbin/sendmail -t.

    Maybe you can instead checkout another transport type like smtp and see if this is working for you?

  • ๐Ÿ‡ช๐Ÿ‡ธSpain henkpotman

    Thanks a lot for your feedback netzkombuese!

    Finally I found out why I got the error message 'Connection to "process /usr/sbin/sendmail -bs" has been closed unexpectedly.'

    I was running the updated site on localhost for testing before uploading it to the production server. However on localhost sendmail isn't installed causing the error message.

    I have uploaded the updated site (Drupal 10.3.5, commerce_invoice 8.x-2.0-rc5 and symfony_mailer 1.5.0.) with the commerce_invoice_no_invoice_duplicate_mail.patch indicated in #22 to the production server and from there the invoice email and .pdf attachment works fine.

  • Latest D10.3 and a low traffic Commerce shop, manual payments only. The patch from #22 fixed the problem for me
    .
    However, now I found out that upon entering manually a received payment a new invoice with โ€žpaidโ€œ in the file name is indeed being generated but not sent. Above it sounded as if this was only tested or fixed and working for PayPal payments. If this holds true for others as well, may I kindly ask fo a fix also for manual payments (or is it a different problem as the patch should cover this use case as well)?

  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany netzkombuese

    @dgwolf

    I just tested this again and the emails with invoices also go out after you have created an order manually. May I ask if you also placed the order? Of course, the emails will only be sent out once the order has been placed. That's the trigger. So after creating a manual order you have to click the Place Order button and everything is working as expected. Thanks

  • Hello netzkombuese, thanks for asking. It is about manually created orders with manual payments as the only payment source. I can place an order, the pending invoice is being created and sent. For this I needed to apply the EntityPrint hotfix patch from here: https://www.drupal.org/project/entity_print/issues/3394857 ๐Ÿ› After clearing caches, the aggregated CSS is not loading properly, which disrupts the layout of the first PDF. Needs work although another issue with CSS was declared resolved but I still had to use the patch. Now when I add a payment it is being received, the open amount is settled and the refund button shows. The mail is being triggered and a "paid" invoice should be attached. It does not happen though and this time I see a PDF has not even been created. When I go to the invoices tab and try to download it the pending invoice can be seen in HTML is gone and instead of a paid invoice I only see "file not found".

    A bit later: Maybe this is now an EntityPrint issue - no invoice is being generated for new orders either although the confirmation mail and the invoice mail are being sent - but wait, three days ago an order was placed and the attached pending invoice arrived at the shop's CC mail address but checking now I see no PDF was saved on the site. I did upgrade to 10.3.6 in the meantime with a few dependencies pulled but this can't be the reason, can it? I'm at a loss how to continue now. Now not even an attached invoice went out (on my testing site with mailhog running).

  • @netzkombuese - I found the time for some more testing on D 10.3.6 with PHP 8.3.11, Symfony Mailer 1.5.0, Commerce 8.x-2.40 and Commerce Invoice 8.x-2.0-rc5 and your patch #22 (which was working well on I think 10.3.4). When I place an order (manual payments only) the invoice pdf is being created (with a patched entity_print for proper CSS rendering), but the pdf doesn't get sent with the outgoing mail. The order confirmation and the mail that should have the invoice attached are being sent alright. The log of the Drupal php container says:

    php-drupal | NOTICE: PHP message: Uncaught PHP Exception TypeError: "call_user_func(): Argument #1 ($callback) must be a valid callback, class Drupal\commerce_invoice\EventSubscriber\InvoiceConfirmationSubscriber does not have a method "sendInvoiceConfirmation"" at /var/www/html/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php line 111
    php-drupal | NOTICE: PHP message: Error: Call to undefined method Drupal\commerce_invoice\EventSubscriber\InvoiceConfirmationSubscriber::destruct() in /var/www/html/web/core/lib/Drupal/Core/DrupalKernel.php on line 723 #0 /var/www/html/web/index.php(22): Drupal\Core\DrupalKernel->terminate()

    I'd be very glad if this could be fixed. Regards, dgwolf

  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany netzkombuese

    @dgwolf I understand what you want to do. For my understanding n Drupal Commerce, invoices and order confirmations are generally triggered when an order is placed. This is because the initial invoice email is meant to confirm the order, so manual payment status updates (like marking a payment as โ€œreceivedโ€) don't typically resend the invoice.
    To send the invoice upon a manual payment update, you would need to customize the workflow to specifically check for payment status changes and trigger the email logic accordingly.

    So this would be another special customization which has to be implemented.
    Unfortunately - at the moment - we don t have resources for setting up and debugging this scenario.

  • Sorry for the late reply, had too many other tasks. Manual orders seemed to work after a complete reinstall of the invoice module and the patches. However, creating manual payments leads to lost invoices that are listed with the orders under the orders tab but the linked file is sometimes missing. Invoices seem to get recreated as "paid" when the payment is entered manually, but not when a rebate is entered under credits and a new invoice with the old total minus the new rebate listed as credit is sent, and not all pathways to manually entered payments seem to trigger the creation of a paid invoice. I am sort of giving up right now. As the main function of invoice creation upon placing an order works I may have to live with the rest.
    When I have a bit more time again I would like to track and debug the invoice creation. Is there a workflow map online somewhere, I am not a programmer but would like to wrap my head around the process flow for creation and storing invoices with the commerce invoice module. And is it possible to let the database look for lost invoices and relink them, if they still exist?

  • This actually was an error message encountered when entering a payment manually. Reloading the page led to the invoice being marked as paid, but in ithis case the "paid" invoice was not created at all, and the "pending" invocice was gone:

    Error: Call to a member function hasTranslation() on null in Drupal\file\Plugin\Field\FieldType\FileFieldItemList->postSave() (line 54 of core/modules/file/src/Plugin/Field/FieldType/FileFieldItemList.php).

    call_user_func_array(Array, Array) (Line: 938)
    Drupal\Core\Entity\ContentEntityStorageBase->invokeFieldMethod('postSave', Object, 1) (Line: 984)
    Drupal\Core\Entity\ContentEntityStorageBase->invokeFieldPostSave(Object, 1) (Line: 896)
    Drupal\Core\Entity\ContentEntityStorageBase->invokeHook('update', Object) (Line: 56)
    Drupal\commerce\CommerceContentEntityStorage->invokeHook('update', Object) (Line: 25)
    Drupal\commerce_invoice\InvoiceStorage->invokeHook('update', Object) (Line: 564)
    Drupal\Core\Entity\EntityStorageBase->doPostSave(Object, 1) (Line: 781)
    Drupal\Core\Entity\ContentEntityStorageBase->doPostSave(Object, 1) (Line: 489)
    Drupal\Core\Entity\EntityStorageBase->save(Object) (Line: 806)
    Drupal\Core\Entity\Sql\SqlContentEntityStorage->save(Object) (Line: 354)
    Drupal\Core\Entity\EntityBase->save() (Line: 72)
    Drupal\commerce_invoice\Form\InvoicePaymentForm->submitForm(Array, Object)
    call_user_func_array(Array, Array) (Line: 129)
    Drupal\Core\Form\FormSubmitter->executeSubmitHandlers(Array, Object) (Line: 67)
    Drupal\Core\Form\FormSubmitter->doSubmitForm(Array, Object) (Line: 597)
    Drupal\Core\Form\FormBuilder->processForm('commerce_invoice_payment_form', Array, Object) (Line: 326)
    Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 73)
    Drupal\Core\Controller\FormController->getContentResult(Object, Object)
    call_user_func_array(Array, Array) (Line: 123)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 638)
    Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 121)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 181)
    Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 76)
    Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 53)
    Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 28)
    Drupal\Core\StackMiddleware\ContentLength->handle(Object, 1, 1) (Line: 32)
    Drupal\big_pipe\StackMiddleware\ContentLength->handle(Object, 1, 1) (Line: 106)
    Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
    Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 50)
    Drupal\ban\BanMiddleware->handle(Object, 1, 1) (Line: 263)
    Drupal\shield\ShieldMiddleware->bypass(Object, 1, 1) (Line: 130)
    Drupal\shield\ShieldMiddleware->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
    Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 36)
    Drupal\Core\StackMiddleware\AjaxPageState->handle(Object, 1, 1) (Line: 51)
    Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object, 1, 1) (Line: 741)
    Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

Production build 0.71.5 2024