Problem/Motivation
Updated for Jan 2025: most of the important work has now been completed.
- As of v1.6, the API is complete including embedding #3382624: embed attachments API addition.
- Attachments in legacy messages such as WebForm are working #3284142: Add support to attachments for LegacyEmailBuilder.
- There is decent simple security protection.
The main remaining work is to add some plugins that use the API.
Proposed resolution
Here are some ideas for how we might use attachments:
- Top priority: #3284140: Email adjuster to attach/embed by scanning the email body
- Field formatter that adds a file as an attachment, for example for simplenews newsletter
- Email adjuster to attach a file which could be from a URL or an existing Drupal managed file or a UI ("browse" button) to upload a new file
- Allow embedding images in BodyEmailAdjuster (possibly supporting the Twig syntax provided by Symfony)
Original issue
Symfony mailer supports embedding images and file attachements (https://symfony.com/doc/5.4/mailer.html#embedding-images / https://symfony.com/doc/5.4/mailer.html#file-attachments). At the moment this has not yet been implemented (as noted in https://www.drupal.org/docs/contributed-modules/symfony-mailer-0/feature...), and the related methods are commented in Drupal\symfony_mailer\BaseEmailTrait.
The OP requested to implement direct support for the symfony mailer functions below. As maintainer, I propose that we start from the requirement discussion above and see what API it leads to.
- attach()
- attachFromPath()
- embed()
- embedFromPath()
- attachPart()
- getAttachments()
Remaining tasks
User interface changes
API changes
Data model changes
| Comment | File | Size | Author |
|---|---|---|---|
| #25 | 2022-05-18 14_42_12-[META] Attachments support [#3261807] _ Drupal.org_.png | 14.4 KB | attisan |
Issue fork symfony_mailer-3261807
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
hchonovI've tested it and it works sending attachemnts through the symfony mail methods.
Comment #3
adamps commentedThanks. It's a good start.
However, these are commented out for a reason, because it's a complex topic that needs some planning. The hardest part is security - we must not allow a user to email themselves a copy of protected files such as settings.php.
Another issue #3261693: Implement embedded images was raise a few hours before yours, and it has more information in the summary, so I'll close this one as a duplicate. You are welcome to add your patch there with a status of "Needs work" as it would likely help some people.
Comment #4
hchonovI am confused why the issue with the patch is being closed. Isn't it easier to copy the information from the other issue? Also please note the other issue mentions everything that has been implemented here already....
Comment #5
seanbAgreed, let's use this issue. I'll close mine as a duplicate.
Comment #6
adamps commentedSure, but in that case please copy in the IS from the other issue rather than only saying that it would be easier to do so (especially it had some good links). Also I now need to repost my comment from the other issue to here and correct the status here to "needs work". So whilst you saved yourself the (tiny) effort of reposting your patch, you made more work for the maintainer😃.
Comment from other issue...
This cannot be committed until the security is done, and that's quite hard. I would also like to test out some different use cases (see "features and status" linked from the IS for some ideas) to confirm the interface is right before commit. In fact I would even say we should have tests for these different use cases - which means we would need to create the testing framework first.
In my mind this is not the top priority for me to spend time on as it seems quite specialised/complex and many of the basics are also still not present. Anyone who is keen to use it earlier can apply the patch.
Comment #7
seanbUpdated the IS.
Comment #8
seanbComment #9
attisanSo, after applying the patch - there still is no way to attach attachments to mails as the methods needed are not exposed within \Drupal\symfony_mailer\Email.php (yet? due to security concerns?)?
Mind if we create an issue fork so we can collaborate on getting this part working?
I'm currently trying to get attachments working (due to the demand for commerce_invoice to actually send invoices).
Comment #10
hchonovThe patch makes the methods public so you can use it to send attachments, however further work is needed to enhance security.
Comment #11
attisanSo how could I use them - sorry for asking. I (until know) planned on creating
\Drupal\commerce_invoice\Plugin\EmailBuilder\CommerceInvoiceEmailBuilderwich would handle adding the attachments from params. But having the\Drupal\symfony_mailer\Email(using the preRender method) I can't access the inner SymfonyEmail object ..?Comment #12
guylyons commentedI'm also curious how to get an attachment working with this patch, and will the work with the BC module enabled? If someone would kindly describe their process, it would be greatly appreciated. Thanks.
Comment #13
rang501 commentedUpdated patch to fix fatal error because DataPart include was missing
Comment #14
sander wemagine commentedThis is an updated patch from #13, this patch will sends attachments from the $params['attachments'] key in mails.
With this patch the Commerce Invoice attachments are being send on my installation. Make sure you enabled the sub module "Symfony Mailer Back-compatibility".
Comment #15
adamps commentedThanks @Sander Wemagine. Patch #14 is very useful because it gives an example of how the API could be used. It would be great if other could upload examples too.
We don't necessarily want to just cope the symfony API - we should make things more "Drupaly". For example a common case will be to attach a Drupal File class, and the attached patch shows an interface for that. We might also want one based on the Drupal Url class. Perhaps we wouldn't so much use
attachPart().I would be interested to understand how the embed methods should be used. I am imagining the case of an embedded image - in which case we need to specify where in the email body the image should be displayed. The body render array could contain a specific render element to generate an embedded image.
Comment #16
attisanCreated a patch (MR) incorporating @AdamPSs ideas regarding some safeguards against being able to attach system files and added a bit of backward compatibility (instead of relying on modules to implement whatever symfony_mailer provides, symfony_mailer should try to provide means to "get going" - else integrators might just opt to use swiftmailer as "things just work").
My patch will not magically make attachments work in any situation. It is but a starting point.
Comment #18
attisanFor the time being, and as stated - to have a starting point - I opted to include basic
attachFromPathonly as that is what modules I know do use; an array of paths to files within the attachment property of the mail params.Comment #19
nojj commentedMR works for me
Comment #20
seanbHere is an example of how we use this to add inline images to mail. Might be good to add something like this to the module in a followup.
Comment #21
attisan@seanB should I add your code to the MR?
Comment #22
adamps commentedThanks for continuing the good work here. I have updated the IS.
I made this issue a META because I believe it will be solved in multiple stages. Already there are many patches each trying to do different things. I suggest that each person could raise a new issue describing specifically what they are trying to do, and adding their patch.
$params['attachments']. I like it, but also I would have some concerns about security.Comment #23
attisanThanks for the feedback @AdamPS. I have the feeling there are many patches - all actually trying to do the same thing - get attachments working with symfony_mailer 😉.
When you suggest moving the security part into the core mailer/email classes, do you have a guideline on how you would like attachments to be handled in first place? Moving to a strictly "drupaly" way will leave many modules and implementations behind as it will strain developers time to make adjustments to accommodate for the changed way of handling emails.
Comment #24
jeroentCreated a patch of #22 in case someone wants to use it.
Comment #25
attisanThough well hidden, MRs can easily be used as patches directly by using the plain diff link 😉 (with the added bonus to stay up to date when things change / get fixed)
Comment #26
jeroentYeah, I don't like the idea that someone with bad intentions can update the MR and break my site.
That's why I always use a patch file, so I control which code is added.
Comment #27
adamps commentedWell I described 4 (now 5) distinct cases in the IS😃. #20 and #14 are quite different.
Not fully. My development here is based on wanting the help the community and also on supporting sites I develop for. I don't need attachments for my own sites, and I'm really busy so it's hard for me to find a lot of time to work on it. However each time someone creates a new patch it really helps develop the overall picture. It would really help if someone could create separate cases listed in the IS, and move patches here to the appropriate new issue. Also I think a patch for case 2 is really important to confirm what would be a good interface.
I understand. This module is trying to balance two different motivations:
If we can get the "clean, simple" case working first, then I'll feel confident we have the right interfaces. Afterwards probably we can maximise legacy support also.
Comment #28
attisanso are we all.
That would really be something I would love to see done by "a" (😋) maintainer - hence my mentioned guideline. Having this done by the community / non-maintainers, I have the feeling that it could end up in more work than necessary when things are implemented in a way, that isn't to your liking. - I'll try anyway if you say so / want me to.
Comment #29
imclean commentedComing in from a non-Symfony Mailer perspective, I'm trying to get my head around this specifics of this task.
To simplify things (for my benefit at least), I imagine there would be 2 ways to add attachments:
There are 2 ways for these to be attached:
Beyond that, there are plenty of ways of getting the file to the email. Some of them would be outside the scope of this module.
To a certain extent this could be handled by the module attaching the file. Files can also be emailed on cron.
Is the above too simple? I'm trying to get a handle on what needs to be done conceptually before getting into the specifics of Symfony Mailer.
Comment #30
jeroent#3281115: Support sending attachments using symfony_mailer got committed so if this issue is fixed, sending attachments using Webform will also work.
Comment #31
adamps commentedOK good idea, but I won't have time until June
Comment #32
attisan@AdamPS I have reviewed your opinion on this and am inclined to disagree with you. Though it might seem like a nice thing to have security directly in the base class, it will (obviously quite often, as it seems attachments aren't a big thing) not be used a lot and hence would be "dead meat" plus adds complexity for maintenance when things change.
Leaving it as an adjuster gives the webpage builder more flexibility over where he wants to enable attachment support (coincidentally adding to the security footprint) and separates this specific topic from the base implementation. Further more, it "feels" more endemic to how other parts of the module have already been implemented (adding adjusters to specific policies as needed).
Having the base email class provide the methods to add / inline attachments won't bear more risk when implemented with or without the "security part" being handled externally as a potential villain, already having access to directly call the method on the email object has very basic system access - simply using fopen would be less hassle 😅.
Comment #33
attisan@AdamPS - side note; I wholeheartedly feel your need to split this issue into smaller sub-issues BUT (😂, there always is a but) it makes development super slow and extra un-comfy (especially when trying to stick to the new-era patch system of creating forks and MRs introduced 2020) as there is no (obvious?) way to create a fork based on an another issues fork. So adding all those needed sub-parts, the fact that this module only has a single maintainer (you), mixed with your tight time schedule "kind of" chokes the currently development and leaves webpage builders either using different patches listed here (so bugs aren't found as fast due to spread usage) or stalls the transition from swfitmailer to symfony_mailer.
Comment #34
nojj commentedMR !22 does not apply together with MR!24 from here
https://www.drupal.org/project/symfony_mailer/issues/3280322
alone they both apply fine.
Comment #35
adamps commentedI created 2 child issues and updated the IS with some comments about the likely interface IMO.
@attisan I don't understand any way to commit this whole issue, because as I already said there are different patches doing quite different things. However each of the child issues I created could be committed.
@imclean #29 roughly matches my thinking
Comment #36
nojj commentedsince MR!22 does not apply to the latest DEV, I have a WSOD at admin/config/system/mailer and don?t know how to fix it.
Comment #37
nojj commentedis anybody working on an updated patch vor attachments for commerce Invoice? as non of the previous patches/MR apply to the latest alpha.
Thanks in advance.
Comment #38
hchonovI've re-rolled #24 but couldn't see how to and if I have to reapply the only single reject as the code has changed too much:
Comment #39
nojj commentedThanks @hchonov !
Patch apples to alpha10 and strangely fixes issue described here:
https://www.drupal.org/project/symfony_mailer/issues/3292133
but it does no send pdf invoices from commerce invoice :-(
the "old" patch did...
Comment #40
hchonovI've added a webform email builder so that I can bring up the webform attachments from the legacy_message when using the BC module to the email parameters. Now you need only to create a Webform policy and add the attachments adjuster and you can send attachments through webforms. I am not sure if we should rather bring this to the LegacyEmailBuilder?
Comment #41
nojj commentedhas anyone tested patch #38 and can send attachments with commerce invoice?
I don't get any error messages, but I also don't get the pdf attached.
Comment #42
nojj commentedMaybe this helps debugging:
with mailhog at the working installation (older dev version of Symfony Mailer and MR22) I get this at MIME
and with patch #40 I get
I can't tell if this is problem with the patch or a setup problem.
Comment #43
adamps commentedThis is now a meta issue so please use other issues for patches:
Comment #44
adamps commented#3284142: Add support to attachments for LegacyEmailBuilder is now fixed.
Comment #45
jrockowitz commentedI am working on getting webforms with email attachments working for a client using the Symfony Mailer module. It took me a little while to figure out the exact steps required, and I wanted to share my notes.
Below are my steps to get Webform email attachments via SMTP.
Comment #46
nojj commentedthanks for the detailed explanation.
Comment #47
adamps commented@jrockowitz Thanks for posting. Please can you recheck your results the latest dev release? Since #3284142: Add support to attachments for LegacyEmailBuilder was fixed as noted in #43, the patch from #40 should not be needed, and will no longer apply.
Comment #48
nchase commentedcan confirm #47 - latest dev works. Attachment from commerce invoice get sent.
Comment #49
jungleRerolled, no interdiff.
Comment #50
jungleFix
Error: Class "Drupal\symfony_mailer_bc\Plugin\EmailBuilder\LegacyEmailBuilder" not found in include() (line 14 of /var/www/html/web/modules/contrib/symfony_mailer/modules/symfony_mailer_bc/src/Plugin/EmailBuilder/WebformEmailBuilder.php)Comment #51
jungleTo get work the issue in comment 11 or 13 of #3310048: Support Symfony Mailer for attachments and deprecate Swiftmailer, if $attachment['filecontent'] exists, use it.
Comment #52
adamps commentedGreat thanks for the patch. This is a meta issue that will stay open until all the parts are done. Please create a new issue for any patch to be committed.
Comment #53
jungleOk, @AdamPS added one with what I encountered and linked the patch in #51 there. #3328847: Support attachments with 'filecontent'
Thanks!
Comment #54
nchase commented#51 works. The attachments uploaded via webform get send via symfony mailer. Thank you!
Comment #55
3cwebdev commentedYes! #51 did the trick and my Webform PDF attachments are now sending again. Thank you :)
Comment #56
adamps commentedNB patch #51 is being developed in #3328847: Support attachments with 'filecontent' and there is a new patch that needs review please. Please put any comments on the other issue.
Comment #57
1i1c commented@jrockowitz
Thank you for detailed explanation. I tried your approach using MailHog and the Webform can send emails with attachments. However, it appears that sending email using sendmail still missing attachments. Any solution for webform without SMTP?
Comment #58
wouter waeytens commentedUpdate patch to work with the latest stable release.
Comment #59
wouter waeytens commentedUpdate patch to work with the latest stable release. Forgot the staged files.
Comment #60
adamps commentedThis is a meta issue and its purpose is to group together related issues. Please create separate issues for each part of the work. Patches here will not be committed.
Comment #61
loopy1492 commentedWell, in the mean-time, thanks for keeping the patches updated @Wouter Waeytens .
Comment #62
adamps commentedComment #63
adamps commentedComment #65
adamps commentedComment #67
adamps commentedI created a branch for proposed resolution #3: Attach file adjuster. It is a work in progress: all you can do is attach an existing Drupal managed file, and there is no browser, so you need to type in the URL.