// How to: | |
// 1) Login into https://icloud.com | |
// 2) Open the developer tools and execute this code in the console | |
// See more @ https://medium.com/bugbountywriteup/how-apple-stored-all-your-email-metadata-for-years-on-their-servers-2a61b1a3232d | |
const _API_URL='https://p18-mailws.icloud.com/wm/recents'; | |
const _requestContacts = () => { | |
console.warn('Requesting your contacts...'); | |
return fetch(_API_URL, { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
}, | |
credentials: 'same-origin', | |
credentials: 'include', | |
body: JSON.stringify({ | |
jsonrpc: '2.0', | |
method: 'list', | |
}), | |
}).catch(error => { | |
console.error('An error happened while trying to list your contacts:', error); | |
}); | |
}, _deleteContacts = (contacts) => { | |
console.warn('Asking the backend to delete data it should not have...'); | |
return fetch(_API_URL, { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
}, | |
credentials: 'same-origin', | |
credentials: 'include', | |
body: JSON.stringify({ | |
jsonrpc: '2.0', | |
method: 'delete', | |
params: { | |
guids: contacts | |
}, | |
}), | |
}).catch(error => { | |
console.error('An error happened while trying to delete your contacts:', error); | |
}); | |
}, listAllContactsDetainedByApple = async () => { | |
const contacts = await (await _requestContacts()).json(); | |
console.warn(`Here is the raw list of the contacts (${contacts.result.length}):`); | |
console.warn(JSON.stringify(contacts)); | |
}, | |
deleteEverythingForever = async () => { | |
const guids = []; | |
const contacts = (await (await _requestContacts()).json()).result; | |
for (const contact of contacts) { | |
if (contact.guid) { | |
console.warn(`Added address ${contact.address} to the deletion list`); | |
guids.push(contact.guid); | |
} | |
// Cover groups as well | |
if (contact.isMemberOf) { | |
for (const group of contact.isMemberOf) { | |
if (group.guid) { | |
console.warn(`Added ${contact.address} (group) to the deletion list`); | |
guids.push(group.guid); | |
} | |
} | |
} | |
} | |
if (guids === undefined || guids.length == 0) { | |
return console.error('No contact to delete'); | |
} | |
const response = await _deleteContacts(guids); | |
console.warn('Done! All your recents contact has been deleted from iCloud Mail.'); | |
console.log(response); | |
}; | |
console.warn(window.atob("DQogXyBfX19fXyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfICAgICAgICAgICAgICAgDQooXykgIF9fIFwgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgfCAgICAgICAgICAgICAgDQogX3wgfF9fKSB8X19fIF8gX18gX19fICAgX19fIF8gX18gX19fIHwgfF9fICAgX19fIF8gX18gDQp8IHwgIF8gIC8vIF8gXCAnXyBgIF8gXCAvIF8gXCAnXyBgIF8gXHwgJ18gXCAvIF8gXCAnX198DQp8IHwgfCBcIFwgIF9fLyB8IHwgfCB8IHwgIF9fLyB8IHwgfCB8IHwgfF8pIHwgIF9fLyB8ICAgDQp8X3xffCAgXF9cX19ffF98IHxffCB8X3xcX19ffF98IHxffCB8X3xfLl9fLyBcX19ffF98ICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg")),console.warn("To see all the email addresses you ever contacted using Apple Mail since the launch of iCloud, run listAllContactsDetainedByApple()"),console.warn("Since Apple does not provide a way to delete everything at once, or even see the full list, you can easily delete everything forever by running deleteEverythingForever()"); |
Just tried it and got the following errors:
() __ \ | |
| |) | _ __ ___ ___ _ __ ___ | |__ ___ _ __
| | _ // _ \ ' _ \ / _ \ '_
_ | '_ \ / _ \ '|
| | | \ \ / | | | | | / | | | | | |) | __/ |
||_| __|| || |_|_|| || ||./ ___|_|
(anonymous) @ VM79:71
VM79:71 To see all the email addresses you ever contacted using Apple Mail since the launch of iCloud, run listAllContactsDetainedByApple()
(anonymous) @ VM79:71
VM79:71 Since Apple does not provide a way to delete everything at once, or even see the full list, you can easily delete everything forever by running deleteEverythingForever()
(anonymous) @ VM79:71
undefined
listAllContactsDetainedByApple()
VM79:7 Requesting your contacts...
_requestContacts @ VM79:7
listAllContactsDetainedByApple @ VM79:42
(anonymous) @ VM81:1
Promise {}proto: Promise[[PromiseStatus]]: "rejected"[[PromiseValue]]: SyntaxError: Unexpected end of JSON input
at listAllContactsDetainedByApple (:42:59)
recents:1 POST https://p18-mailws.icloud.com/wm/recents 500 (Internal Server Error)
VM79:42 Uncaught (in promise) SyntaxError: Unexpected end of JSON input
at listAllContactsDetainedByApple (:42:59)
listAllContactsDetainedByApple @ VM79:42
async function (async)
listAllContactsDetainedByApple @ VM79:41
(anonymous) @ VM81:1
listAllContactsDetainedByApple()
VM79:7 Requesting your contacts...
_requestContacts @ VM79:7
listAllContactsDetainedByApple @ VM79:42
(anonymous) @ VM84:1
Promise {}
VM34:1 POST https://p18-mailws.icloud.com/wm/recents 500 (Internal Server Error)
(anonymous) @ VM34:1
_requestContacts @ VM79:8
listAllContactsDetainedByApple @ VM79:42
(anonymous) @ VM84:1
VM79:42 Uncaught (in promise) SyntaxError: Unexpected end of JSON input
at listAllContactsDetainedByApple (:42:59)
listAllContactsDetainedByApple @ VM79:42
async function (async)
listAllContactsDetainedByApple @ VM79:41
(anonymous) @ VM84:1
Hey @pwnsdx I'm grateful you managed to create and share this code! It works well, although there does seem to be problem I can't get rid of. Even though "Groups" are part of the code, these groups are the only things that still show up when I compose an email in iCloud Mail (web interface). This happens even when all the contacts were deleted successfully using your code. I'm not as tech savvy as you are, so I was wondering if you are able to look into this and perhaps find a solution? :)
In addition to my comment, I’ll share some extra context. Using the Developer menu in Safari I was able to find the source in which the recipients that are part of a “group” are located (see attached). In my case there are two groups, both consisting of two recipients. This matches the XML format which is located under Other data > Apple Features Using iCloud > Mail > Recents.xml following a GDPR request I submitted to Apple for access to my data. As I noted, all individual recipients have been succesfully deleted using iRemember, but these groups (i.e. a combination of recipients) seem to require a slightly different approach. At this point I’m lacking the technical skills to adjust your code and make it work. I did try tweaking some things but being a layperson in coding I have no idea what I’m doing. Help from this community is much appreciated! :)
TLDR; I too could use what @DaanQ is requesting.
The iRemember tool worked very well for removing single recipient suggested contacts, but after 10 years of working for a CSP, there are many hundreds of "suggested contacts" that contain multiple recipients. Now that I have taken a new position with a different company, these contacts are still showing up even though all email and unnecessary contacts have been removed from my iPhone/iCloud accounts. Any help would be greatly appreciated to help clean this up.
Hi @pwnsdx, I registered here only because I wanted to delete my data using this script, but unfortunately I get error 500 with both commands. I tried it with both Firefox and Ungoogled Chromium, disabled my add-ons, created a new Firefox profile and ran the commands again to no avail. I don't know what I am doing wrong. Any help would be greatly appreciated.
Holy. Shit.
To remove the groups, edit line 47 so that the guids
array contains the recentId
of the group to delete too.
So in the screenshot @DaanQ posted, take the recentId
of each group. It should begin with GP_
.
Then change line 47 to const guids = ["recents:GP_ABC", "recents:GP_XYZ];
, replacing GP_ABC/GP_XYZ with your recentId
(keep the recents:
prefix). Run deleteEverythingForever()
, which will remove the groups listed.
I only had one group to remove, so this was fine for me. But if you have a lot of groups, then it might be annoying to list all of them.
@gordonwang0 Thanks a lot for your help, your instructions worked flawlessly in my case! All recent recipients and groups are deleted now. Really happy with it :)
@rummtron I hope it will work for you as well!
Thanks also from my side, I could finally get rid of all those dead entries always showing up in icloud.
However there is one record in my case remaining, i cant get it deleted with directly adding to the guids.
Using the p18-mailws doesnt show it at all, but in the dev console, i see it in the recents at p120-mcc.
The only difference to all others is
reciepientEmail has no maildomain, so just user, i.e. from local mails and senderApp is also not set at all and recipientName is emptyString.
Any chance to get rid of that one? I hope Apple does not check field validity on deletion ...
n
Hello @pwnsdx , thank you for sharing this scripts, and I meet an issue. I ran this scripts, and got tips No contact to delete
, please check this picture.
But the suggestion still remains when i compose a new mail. Any ideas?
sqers commentedJun 1, 2018