back to

GDPR: Delete instead of blacklist / time and date of confirmation


Due to european law (GDPR) it is necessary to delete all user data immediately, if an user unsubribes from a newsletter. Now an user ist blacklisted after signing of, so that his email adress is still saved in the database. Unfortunately that is illegal in europe. How can this data be deteled automaticaly after unsubscription?

Also it’s required to store time an date, when a new user confirmed the registration. At the moment only the time an date of registration will be stored, not the date and time of confirmation.

Is there a solution to comply with the requirements of law (f.ex. with a plugin)?


@arada Confirmation is recorded as well as the initial subscription. It should look like this on your subscriber history pages (two separate entries)


I think you have some leeway with deleting blacklisted users, but I agree they cannot stay in the database indefinitely. The solution I came up with is a mixture of phpMyAdmin and phpList.

I have phpmyAdmin via my cPanel interface. You may have it elsewhere, or if not you may be able to run the sql command described below.

Having logged in to phpMyAdmin navigate to the user_user table and run this sql command (it might be prudent to back up first!): ‘whatever’ is a placeholder.
UPDATE whatever_user_user SET bouncecount = 11 WHERE blacklisted = 1
This will set the bouncecount on all blacklisted users to 11. Then use the reconcile users facility in phpList to delete all users with more than 10 bounces.


What I’d like to see, for compliance with the GDPR without trashing data, would be for an unsubscription request to replace the email address with a one-way hash of the email address, set all attributes to a blank or default value, and blacklist that subscriber record. This way the records would remain but we would no longer have the person’s actual data. This could also be done with a unique replacement value (e.g., UUID), but a one-way hash could be used (with extra processing, of course) to prevent accidentally re-importing a blacklisted address.

Simply deleting data leaves us open to re-importing the same data against the person’s wishes, either by accident or through someone maliciously using our list to harass someone else.

Of course it’s easy to say what I want without writing any code. If I could, I would try to contribute this myself. That’s not feasible for me to do at the moment, unfortunately.


@Crenel84 Good proposal, thanks.

What stops this from being implemented right away is that changing the subscriber email address to a value which is not in fact an email address would likely have unintended consequences that would need very thorough testing (of most parts of the app). Hashing may also have a big impact on performance (consider installations with >100m subscribers) that would require investigation.

It is faster to simply delete data, including related blacklist data, though doing so retrospectively changes campaign statistics, and risks reimport. The next release willmknclude more options for deleting data. Hopefully obfuscation as an alternative will be added in future.


Performance would definitely be a concern. I have no suggestion for that! On the flip side, if it doesn’t break entirely, I would choose a performance hit over a legal liability hit.

Maintaining a valid address should be an easier nut to crack. The domain is specifically an evergreen domain used for examples (e.g., in documentation) and mail to it goes nowhere or (as far as I know and have tested) even bounce. ${hashvalue} would be a valid, informative, safe, and algorithmically easy (to create and to detect) replacement email address.


I like your thinking. It feels like a workaround, which I feel it’s best to avoid, but perhaps an acceptable one given the challenges involved in alternative approaches. Partially hashing the address would result in an even greater potential performance hit (due to pulling apart the components of the address to extract the hash before use). However this seems like one relatively quick path to a solution.

@michiel may wish to comment.


Would you need to pull it apart later? I’m seeing the concatenated string as essentially a hash itself, only part of which is based on the original value. So, for example, when preventing re-import of a blocked address, the “new” address would be hashed, the string concatenated, and then the resulting value verified to not be blacklisted.

I might be missing something… I haven’t had any coffee yet today. And I think I’m coming up with cohesive sentences, so that’s something!


Turns out that mail to is not automatically sent to the bit bucket, although that would presumably be up to the sending system. My test message from Gmail end up being processed normally. The domain doesn’t receive anything, so Gmail told me it’ll keep trying to deliver it for awhile.

This shouldn’t really be a problem, though, because the hashed “addresses” are already blacklisted, so no mail is being sent to them anyway.

I wish I had the time and existing knowledge of phpList plugins, this seems like a good plugin (“Hash Blacklisted Addresses” …?). That way those who don’t want the functionality wouldn’t be troubled with it, but those who want (or feel they need) it could optionally install the plugin. I could figure it out but by the time I got it ready the GDPR would already be in effect.


@Crenel84 I think that it would be better as core functionality as enough people are affected by this use case. Your hashing approach sounds interesting. Perhaps it will be picked up by a developer.


@Crenel84 FYI are right about leeway regarding maintenance of a suppression list. This official advice from the UKs Data Protection authority has this to say:

The right to object to direct marketing under Article 21(3) does not prevent a controller from holding a suppression list, as the list supports the individual’s right to object and is held for compliance rather than for direct marketing purposes

phpList GDPR compliance : defects and improvements suggestions
Using phpList for compliance with the GDPR: manual chapter feedback and discussion

Ah, that’s good. And in this case being blacklisted in phpList is effectively a suppression list, right? (I know there’s a suppression list function in phpList but I don’t understand how that fits into things and I’m not even seeing anything about it in the manual.) This is much easier than messing with hashing addresses as a way to “delete” them.

If a person specifically requests deletion of the data I have for them, it seems I should still be in compliance if I erase their attributes in phpList but leave their email in the system, marked as blacklisted. That way I’ve deleted information I don’t have a reason to keep but have held data for compliance. I think it’s reasonable to assume that the held-for-compliance data should also include data about how they were added to the system in the first place, which conveniently avoids the need to get into the database directly to clear those values.



Yes that’s my reading.