Intuition of This Feature

One of our clients requests that the webform send emails with the files uploaded through the form (which is feasible via Webform > Email / Handlers), but they do not want the Drupal system to store any submission data (form data) or uploaded files (including in Drupal’s private file system). In other words, they require the webform submission to self-destruct immediately after the email is sent.

While turning off the submission data is simple, by going to “Webform > Settings > General” and check the “Disable saving of submissions” toggle (see screenshot: link), there is no built-in feature to delete the private files upon email submission.

I thought about deleting it via a CRON job (e.g. rm -rf site/default/files/private/webform/webform_machine_name/* -> cron_bash.sh) , but then if a user would to submit an email just the second before the CRON job ran, his files might have a chance to be deleted before the webform triggers the email send (the files may be lost during this process). Moreover, this does not guarantee the timeliness of the deletion, the CRON job can only run as frequent as 1min/execution, and that’s just not good enough !


Override Default Email Handler

this method is ⚠️NOT RECOMMENDED⚠️, as it only works if there’s a single email handler,

if you are dealing with multiple email handler, the very first email submission would trigger the deletion of files, making the files unavailable to all the upcoming email handlers, raising error: Warning: file_get_contents(private://webform/contact/.../example.pdf): Failed to open stream: "Drupa/Core\StreamWrapper\PrivateStream:stream_open" call failed in Drupa/\webform\Plugin\WebformElement\WebformManagedFileBase->getEmailAttachments) (line 1461 of modules/contrib/webform/src/Plugin/WebformElement/WebformManagedFileBase.php).

2026-01-19T140812

Exploration

Below are the scribble notes of steps I’ve been through to figure this method out:

  1. Randomly adding XDebug breakpoint / logging to find an entry point (since I can find nothing on the official document about the presence of any hook that is capable of overriding the default webform email behaviour):

    1-add-log-in-an-effort-to-find-handler-function

  2. Found this sendMessage() function in file: <root>/modules/contrib/webform/src/Plugin/WebformHandler/EmailWebformHandler.php being trigged upon webform submission that is responsible for sending the email:

    2-showcase-xdebug-break-on-sendMessage

  3. Making some inline modification to attempt to modify the default behaviour in Drupal\webform\Plugin\WebformHandler\EmailWebformHandler (to delete all files in the corresponding private directory upon successful email submission):

    3-adding-additional-logic-inplace-to-test

  4. Turning the changes into a installable custom module that extends the Drupal\webform\Plugin\WebformHandler\EmailWebformHandler to modify its sendMessage behaviour:

2025-11-20T130030

Solution

Custom module webform_email_cleanup that purge the private system of webform upon successful email sending: module / custom / webform_email_cleanup.zip

*to container additional webform, please modify the sendMessage() function to include your webform machine name at line-33 :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class EmailWebformHandler extends OriginalEmailWebformHandler {
  public function sendMessage(WebformSubmissionInterface $webform_submission, array $message) {

    // Call parent sendMessage to send the email.
    $result_send = parent::sendMessage($webform_submission, $message);

    // Clean up uploaded email attachment files after sending for certain webforms.
    if($result_send){

            // Check if the webform is 'contact_or_enquiry_webform'
            // and handler the last email handler of this webform.
            if ($this->webform->id() === 'contact_or_enquiry_webform') {
                if ($this->handler_id === $this->getLastEmailHandlerId()) {
                    $this->cleanupAttachmentFiles($webform_submission);
                }
            }

            // More webforms example ....
            if ($this->webform->id() === 'example_webform_1') {
                if ($this->handler_id === $this->getLastEmailHandlerId()) {
                    $this->cleanupAttachmentFiles($webform_submission);
                }
            }

            // More webforms example ....
            if ($this->webform->id() === 'example_webform_2') {
                if ($this->handler_id === $this->getLastEmailHandlerId()) {
                    $this->cleanupAttachmentFiles($webform_submission);
                }
            }

+            // Check if the webform is 'contact'
+            // and handler the last email handler of this webform.
+            if ($this->webform->id() === 'contact') {
+                if ($this->handler_id === $this->getLastEmailHandlerId()) {
+                    $this->cleanupAttachmentFiles($webform_submission);
+                }
+            }
    }

    // Return only the send status (alike the original function).
    return $result_send;
  }

Showcase

2026-01-22T145943

2026-01-22T150044


Create Custom Handler

Failed !!!

this method is ⚠️NOT RECOMMENDED⚠️, as it raise error when the “webform settings > general > disable saving of submissions” option is toggled on; And when “saving of submission” is on, it will still only delete the 2nd last submission while keeping the first submission.

This custom handler method is inspired and based upon this post on Medium:

How To Create a Custom Webform Handler In Drupal (by Sergio Guardiola Herrador)

In this method, instead of override the default email handler, you will need to implement a custom handler in custom module, that you will add manually to the “Webform > Settings > Emails / Handlers” configuration page:

(⚠️ THE FOLLOWING ISSUES ARE ALSO STILL PENDING TO RESOLVE ⚠️)

PENDING …. GOT ERROR DURING IMPLMENTATION…. STILL AWAITING TO RESOLVE ….

(in the second/third screenshot, you can see email attachment cannot be found)

And I believe this is with to do the function invokeWebformElements in file WebformSubmissionStorage.php, it will be called after the email handler’s sendMessage function (it will try to copy the submission data from one place to another place, you can try this by adding a breakpoint on the line-1246 in the below code snippet):

The webform seems to have the following trade off….

  • OPTION1: ONLY DELETE PREVIOUS SUBMISSION

    • enable “submission” such that the files will get copied (then deleted) from the “webform/webform_id/_sid_” folder to its corresponding submission folder (e.g. webform/webform_id/37)

    • then in the handler you can use if ($file === '.' || $file === '..' || $file === '_sid_') to delete the previous submission, but exclude the _sid_ folder, because it will be later used by invokeWebformElements function to copy the files over to its submission folder

  • OPTION2: DISABLE SUBMISSION

    • though there’s no files in submission folder (e.g. webform/webform_id/37)

    • there’re files remaining in the “webform/webform_id/_sid_” folder

    • maybe there’s a way to clear those without raising warning/error, but I don’t know yet ….

Below are the partial working progress of the custom module I build for this method: webform_handler_cleanup.zip


Reference