├── .gitignore ├── LICENSE ├── README.md ├── logo.png ├── mailcat.py └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mailcat 2 | 3 |

4 | 5 |

6 | 7 | --- 8 | 9 | The only cat who can find existing email addresses by nickname. 10 | 11 | ## Usage 12 | 13 | First install requirements: 14 | 15 | pip3 install -r requirements.txt 16 | 17 | Then just run the script: 18 | 19 | ./mailcat.py username 20 | 21 | It's recommended to run script through Tor or proxy. You can use internal Tor routing (`--tor`) or proxychains. 22 | Examples: 23 | 24 | ./mailcat.py --tor username 25 | proxychains4 -q python3 mailcat.py username 26 | 27 | ./mailcat.py username --proxy http://1.2.3.4:8080 28 | 29 | ## Supported providers 30 | 31 | Total 37 providers, > 170 domains and > 100 aliases. 32 | 33 | | Name | Domains | Method | 34 | | ------------------- | -------------------------------------- | ----------------- | 35 | | Gmail | gmail.com | SMTP | 36 | | Yandex | yandex.ru + 5 aliases | SMTP | 37 | | Protonmail | protonmail.com + 2 aliases | API | 38 | | iCloud | icloud.com, me.com, mac.com | Access recovery | 39 | | MailRu | mail.ru + 4 other domains | Registration | 40 | | Rambler | rambler.ru + 5 other domains | Registration | 41 | | Tutanota | tutanota.com + 4 other domains | Registration | 42 | | Yahoo | yahoo.com | Registration | 43 | | Outlook | outlook.com, hotmail.com | Registration | 44 | | Zoho | zohomail.com | Registration | 45 | | Lycos | lycos.com | Registration | 46 | | Eclipso | eclipso.eu + 9 other domains | Registration | 47 | | Posteo | posteo.net + 50 aliases | Registration | 48 | | Mailbox.org | mailbox.org | Registration | 49 | | Firemail | firemail.de + 2 other domains | Registration | 50 | | Fastmail | fastmail.com | Registration | 51 | | StartMail | startmail.com | Registration | 52 | | KOLABNOW | kolabnow.com + 23 aliases | Registration | 53 | | bigmir)net | i.ua, ua.fm, email.ua | Registration | 54 | | Xmail | xmail.net | Registration | 55 | | Ukrnet | ukr.net | Registration | 56 | | Runbox | runbox.com + 30 other domains | Registration | 57 | | DuckGo | duck.com | Registration | 58 | | HushMail | hushmail.com + 5 other domains | Registration | 59 | | CTemplar | ctemplar.com | Registration | 60 | | emailn | emailn.de | Registration | 61 | | aikq | aikq.de + 40 other domains | Registration | 62 | | Vivaldi | vivaldi.net | Registration | 63 | | mailDe | mail.de | SMTP | 64 | | Wirtualna Polska | wp.pl | Registration | 65 | | Gazeta.pl | gazeta.pl | Registration | 66 | | int.pl | int.pl | Registration | 67 | | O2 | o2.pl | Registration | 68 | | Interia | interia.pl + 10 other domains | Password recovery | 69 | | t.pl | t.pl + 8 other domains | Registration | 70 | | onet.pl | onet.pl + 11 other domains & 4 aliases | Registration | 71 | 72 | ## Troubleshooting 73 | 74 | Use `-m` or `--max-connections` if you get connection errors (Mailcat do 10 parallel connections max by default). 75 | 76 | ### SOWEL classification 77 | 78 | This tool uses the following OSINT techniques: 79 | - [SOTL-2.2. Search For Accounts On Other Platforms](https://sowel.soxoj.com/other-platform-accounts) 80 | - [SOTL-6.1. Check Logins Reuse To Find Another Account](https://sowel.soxoj.com/logins-reuse) 81 | - [SOTL-6.2. Check Nicknames Reuse To Find Another Account](https://sowel.soxoj.com/nicknames-reuse) 82 | 83 | ## Mentions and articles 84 | 85 | [OSINTEditor Sunday Briefing: Sensational Headlines and Kuomintang Chairmanship Elections]([https://www.osinteditor.com/general/osinteditor-sunday-briefing-sensational-headlines-and-kuomintang-chairmanship-elections/](https://web.archive.org/web/20220116223051/https://www.osinteditor.com/general/osinteditor-sunday-briefing-sensational-headlines-and-kuomintang-chairmanship-elections/)) 86 | 87 | [Michael Buzzel: 237 - The Huge OSINT Show by The Privacy, Security, & OSINT Show](https://soundcloud.com/user-98066669/237-the-huge-osint-show) 88 | 89 | [bellingcat: First Steps to Getting Started in Open Source Research](https://www.bellingcat.com/resources/2021/11/09/first-steps-to-getting-started-in-open-source-research/) 90 | 91 | [OS2INT verifying email addresses using Mailcat](https://os2int.com/toolbox/verifying-email-usernames-using-mailcat/) 92 | 93 | [hwosint - Twitter post](https://twitter.com/harrywald80/status/1439115143485534212) 94 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharsil/mailcat/849b32d1604a2809e296345f7ff82e0f1e09ff81/logo.png -------------------------------------------------------------------------------- /mailcat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import aiohttp 3 | import asyncio 4 | import argparse 5 | import base64 6 | import datetime 7 | import json 8 | import logging 9 | import random 10 | import aiosmtplib 11 | import string as s 12 | import sys 13 | import time 14 | import threading 15 | import re 16 | from time import sleep 17 | from typing import Iterable, Dict, List, Callable, Tuple, Any 18 | 19 | import dns.resolver 20 | 21 | import tqdm 22 | # uses pyppeteer 23 | from requests_html import AsyncHTMLSession # type: ignore 24 | from aiohttp_socks import ProxyConnector 25 | 26 | 27 | # TODO: move to main function 28 | uaLst = [ 29 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36", 30 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36", 31 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36", 32 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15", 33 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36", 34 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Safari/537.36", 35 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36", 36 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36" 37 | ] 38 | 39 | logging.getLogger('asyncio').setLevel(logging.CRITICAL) 40 | logging.basicConfig(format='%(message)s') 41 | logger = logging.getLogger('mailcat') 42 | logger.setLevel(100) 43 | 44 | QueryDraft = Tuple[Callable, List, Dict] 45 | 46 | 47 | class stub_progress: 48 | def __init__(self, total): 49 | pass 50 | 51 | def update(self, *args, **kwargs): 52 | pass 53 | 54 | def close(self, *args, **kwargs): 55 | pass 56 | 57 | def create_task_func(): 58 | if sys.version_info.minor > 6: 59 | create_asyncio_task = asyncio.create_task 60 | else: 61 | loop = asyncio.get_event_loop() 62 | create_asyncio_task = loop.create_task 63 | return create_asyncio_task 64 | 65 | 66 | class AsyncExecutor: 67 | def __init__(self, *args, **kwargs): 68 | self.logger = kwargs['logger'] 69 | 70 | async def run(self, tasks: Iterable[QueryDraft]): 71 | start_time = time.time() 72 | results = await self._run(tasks) 73 | self.execution_time = time.time() - start_time 74 | self.logger.debug(f'Spent time: {self.execution_time}') 75 | return results 76 | 77 | async def _run(self, tasks: Iterable[QueryDraft]): 78 | await asyncio.sleep(0) 79 | 80 | 81 | class AsyncioProgressbarQueueExecutor(AsyncExecutor): 82 | def __init__(self, *args, **kwargs): 83 | super().__init__(*args, **kwargs) 84 | self.workers_count = kwargs.get('in_parallel', 10) 85 | self.progress_func = kwargs.get('progress_func', tqdm.tqdm) 86 | self.queue = asyncio.Queue(self.workers_count) 87 | self.timeout = kwargs.get('timeout') 88 | 89 | async def increment_progress(self, count): 90 | update_func = self.progress.update 91 | if asyncio.iscoroutinefunction(update_func): 92 | await update_func(count) 93 | else: 94 | update_func(count) 95 | await asyncio.sleep(0) 96 | 97 | async def stop_progress(self): 98 | stop_func = self.progress.close 99 | if asyncio.iscoroutinefunction(stop_func): 100 | await stop_func() 101 | else: 102 | stop_func() 103 | await asyncio.sleep(0) 104 | 105 | async def worker(self): 106 | while True: 107 | try: 108 | f, args, kwargs = self.queue.get_nowait() 109 | except asyncio.QueueEmpty: 110 | return 111 | 112 | query_future = f(*args, **kwargs) 113 | query_task = create_task_func()(query_future) 114 | try: 115 | result = await asyncio.wait_for(query_task, timeout=self.timeout) 116 | except asyncio.TimeoutError: 117 | result = kwargs.get('default') 118 | 119 | self.results.append(result) 120 | await self.increment_progress(1) 121 | self.queue.task_done() 122 | 123 | async def _run(self, queries: Iterable[QueryDraft]): 124 | self.results: List[Any] = [] 125 | 126 | queries_list = list(queries) 127 | 128 | min_workers = min(len(queries_list), self.workers_count) 129 | 130 | workers = [create_task_func()(self.worker()) for _ in range(min_workers)] 131 | 132 | self.progress = self.progress_func(total=len(queries_list)) 133 | 134 | for t in queries_list: 135 | await self.queue.put(t) 136 | 137 | await self.queue.join() 138 | 139 | for w in workers: 140 | w.cancel() 141 | 142 | await self.stop_progress() 143 | return self.results 144 | 145 | 146 | def randstr(num): 147 | return ''.join(random.sample((s.ascii_lowercase + s.ascii_uppercase + s.digits), num)) 148 | 149 | 150 | async def sleeper(sList, s_min, s_max): 151 | for ind in sList: 152 | if sList.index(ind) < (len(sList) - 1): 153 | await asyncio.sleep(random.uniform(s_min, s_max)) 154 | 155 | 156 | def via_proxy(proxy_str): 157 | def via(): 158 | connector = ProxyConnector.from_url(proxy_str) 159 | session = aiohttp.ClientSession(connector=connector) 160 | return session 161 | 162 | return via 163 | 164 | 165 | def via_tor(): 166 | connector = ProxyConnector.from_url('socks5://127.0.0.1:9050') 167 | return aiohttp.ClientSession(connector=connector) 168 | 169 | 170 | def simple_session(): 171 | return aiohttp.ClientSession() 172 | 173 | 174 | async def code250(mailProvider, target, timeout=10): 175 | target = target 176 | providerLst = [] 177 | 178 | error = '' 179 | 180 | randPref = ''.join(random.sample(s.ascii_lowercase, 6)) 181 | fromAddress = f"{randPref}@{mailProvider}" 182 | targetMail = f"{target}@{mailProvider}" 183 | 184 | records = dns.resolver.Resolver().resolve(mailProvider, 'MX') 185 | mxRecord = records[0].exchange 186 | mxRecord = str(mxRecord) 187 | 188 | try: 189 | server = aiosmtplib.SMTP(timeout=timeout, validate_certs=False) 190 | # server.set_debuglevel(0) 191 | 192 | await server.connect(hostname=mxRecord) 193 | await server.helo() 194 | await server.mail(fromAddress) 195 | code, message = await server.rcpt(targetMail) 196 | 197 | if code == 250: 198 | providerLst.append(targetMail) 199 | 200 | message_str = message.lower() 201 | if 'ban' in message_str or 'denied' in message_str: 202 | error = message_str 203 | 204 | except aiosmtplib.errors.SMTPRecipientRefused: 205 | pass 206 | except Exception as e: 207 | logger.error(e, exc_info=True) 208 | error = str(e) 209 | 210 | return providerLst, error 211 | 212 | 213 | async def gmail(target, req_session_fun, *args, **kwargs) -> Dict: 214 | result = {} 215 | gmailChkLst, error = await code250("gmail.com", target, kwargs.get('timeout', 10)) 216 | if gmailChkLst: 217 | result["Google"] = gmailChkLst[0] 218 | 219 | await asyncio.sleep(0) 220 | return result, error 221 | 222 | 223 | async def yandex(target, req_session_fun, *args, **kwargs) -> Dict: 224 | result = {} 225 | yaAliasesLst = ["yandex.by", 226 | "yandex.kz", 227 | "yandex.ua", 228 | "yandex.com", 229 | "ya.ru"] 230 | yaChkLst, error = await code250("yandex.ru", target, kwargs.get('timeout', 10)) 231 | if yaChkLst: 232 | yaAliasesLst = [f'{target}@{yaAlias}' for yaAlias in yaAliasesLst] 233 | yaMails = list(set(yaChkLst + yaAliasesLst)) 234 | result["Yandex"] = yaMails 235 | 236 | await asyncio.sleep(0) 237 | return result, error 238 | 239 | 240 | async def proton(target, req_session_fun, *args, **kwargs) -> Dict: 241 | result = {} 242 | 243 | protonLst = ["protonmail.com", "protonmail.ch", "pm.me", "proton.me"] 244 | protonSucc = [] 245 | sreq = req_session_fun() 246 | 247 | protonURL = f"https://account.proton.me/api/core/v4/users/available?Name={target}" 248 | 249 | headers = { "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0", 250 | "Accept": "application/vnd.protonmail.v1+json", 251 | "Accept-Language": "en-US,en;q=0.5", 252 | "Accept-Encoding": "gzip, deflate", 253 | "Referer": "https://mail.protonmail.com/create/new?language=en", 254 | "x-pm-appversion": "web-account@5.0.18.4", 255 | "Cache-Control": "no-cache", 256 | "Pragma": "no-cache", 257 | "DNT": "1", "Connection": "close"} 258 | 259 | try: 260 | 261 | chkProton = await sreq.get(protonURL, headers=headers, timeout=kwargs.get('timeout', 5)) 262 | 263 | async with chkProton: 264 | if chkProton.status == 409: 265 | resp = await chkProton.json() 266 | exists = resp['Error'] 267 | if exists == "Username already used": 268 | protonSucc = [f"{target}@{protodomain}" for protodomain in protonLst] 269 | 270 | except Exception as e: 271 | logger.error(e, exc_info=True) 272 | 273 | if protonSucc: 274 | result["Proton"] = protonSucc 275 | 276 | await sreq.close() 277 | 278 | return result 279 | 280 | 281 | async def mailRu(target, req_session_fun, *args, **kwargs) -> Dict: 282 | result = {} 283 | 284 | # headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0', 'Referer': 'https://account.mail.ru/signup?from=main&rf=auth.mail.ru'} 285 | mailRU = ["mail.ru", "bk.ru", "inbox.ru", "list.ru", "internet.ru"] 286 | mailRuSucc = [] 287 | sreq = req_session_fun() 288 | 289 | for maildomain in mailRU: 290 | try: 291 | headers = {'User-Agent': random.choice(uaLst)} 292 | mailruMail = f"{target}@{maildomain}" 293 | data = {'email': mailruMail} 294 | 295 | chkMailRU = await sreq.post('https://account.mail.ru/api/v1/user/exists', headers=headers, data=data, timeout=5) 296 | 297 | async with chkMailRU: 298 | if chkMailRU.status == 200: 299 | resp = await chkMailRU.json() 300 | if exists := resp['body']['exists']: 301 | mailRuSucc.append(mailruMail) 302 | 303 | except Exception as e: 304 | logger.error(e, exc_info=True) 305 | 306 | await asyncio.sleep(random.uniform(0.5, 2)) 307 | 308 | if mailRuSucc: 309 | result["MailRU"] = mailRuSucc 310 | 311 | await sreq.close() 312 | 313 | return result 314 | 315 | 316 | async def rambler(target, req_session_fun, *args, **kwargs) -> Dict: # basn risk 317 | result = {} 318 | 319 | ramblerMail = ["rambler.ru", "lenta.ru", "autorambler.ru", "myrambler.ru", "ro.ru", "rambler.ua"] 320 | ramblerSucc = [] 321 | sreq = req_session_fun() 322 | 323 | for maildomain in ramblerMail: 324 | 325 | try: 326 | targetMail = f"{target}@{maildomain}" 327 | 328 | # reqID = ''.join(random.sample((s.ascii_lowercase + s.ascii_uppercase + s.digits), 20)) 329 | reqID = randstr(20) 330 | userAgent = random.choice(uaLst) 331 | ramblerChkURL = "https://id.rambler.ru:443/jsonrpc" 332 | 333 | # "Referer": "https://id.rambler.ru/login-20/mail-registration?back=https%3A%2F%2Fmail.rambler.ru%2F&rname=mail¶m=embed&iframeOrigin=https%3A%2F%2Fmail.rambler.ru", 334 | 335 | headers = {"User-Agent": userAgent, 336 | "Referer": "https://id.rambler.ru/login-20/mail-registration?utm_source=head" 337 | "&utm_campaign=self_promo&utm_medium=header&utm_content=mail&rname=mail" 338 | "&back=https%3A%2F%2Fmail.rambler.ru%2F%3Futm_source%3Dhead%26utm_campaign%3Dself_promo%26utm_medium%3Dheader%26utm_content%3Dmail" 339 | "¶m=embed&iframeOrigin=https%3A%2F%2Fmail.rambler.ru&theme=mail-web", 340 | "Content-Type": "application/json", 341 | "Origin": "https://id.rambler.ru", 342 | "X-Client-Request-Id": reqID} 343 | 344 | ramblerJSON = {"method": "Rambler::Id::login_available", "params": [{"login": targetMail}], "rpc": "2.0"} 345 | ramblerChk = await sreq.post(ramblerChkURL, headers=headers, json=ramblerJSON, timeout=5) 346 | 347 | async with ramblerChk: 348 | if ramblerChk.status == 200: 349 | try: 350 | resp = await ramblerChk.json(content_type=None) 351 | exist = resp['result']['profile']['status'] 352 | if exist == "exist": 353 | ramblerSucc.append(targetMail) 354 | # print("[+] Success with {}".format(targetMail)) 355 | # else: 356 | # print("[-]".format(ramblerChk.text)) 357 | except KeyError as e: 358 | logger.error(e, exc_info=True) 359 | 360 | await asyncio.sleep(random.uniform(4, 6)) # don't reduce 361 | 362 | except Exception as e: 363 | logger.error(e, exc_info=True) 364 | 365 | if ramblerSucc: 366 | result["Rambler"] = ramblerSucc 367 | 368 | await sreq.close() 369 | 370 | return result 371 | 372 | 373 | async def tuta(target, req_session_fun, *args, **kwargs) -> Dict: 374 | result = {} 375 | 376 | headers = { 377 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'} 378 | 379 | tutaMail = ["tutanota.com", "tutanota.de", "tutamail.com", "tuta.io", "keemail.me"] 380 | tutaSucc = [] 381 | sreq = req_session_fun() 382 | 383 | for maildomain in tutaMail: 384 | 385 | try: 386 | 387 | targetMail = f"{target}@{maildomain}" 388 | tutaURL = "https://mail.tutanota.com/rest/sys/mailaddressavailabilityservice?_body=" 389 | 390 | tutaCheck = await sreq.get( 391 | f'{tutaURL}%7B%22_format%22%3A%220%22%2C%22mailAddress%22%3A%22{target}%40{maildomain}%22%7D', 392 | headers=headers, 393 | timeout=kwargs.get('timeout', 5), 394 | ) 395 | 396 | 397 | async with tutaCheck: 398 | if tutaCheck.status == 200: 399 | resp = await tutaCheck.json() 400 | exists = resp['available'] 401 | 402 | if exists == "0": 403 | tutaSucc.append(targetMail) 404 | 405 | await asyncio.sleep(random.uniform(2, 4)) 406 | 407 | except Exception as e: 408 | logger.error(e, exc_info=True) 409 | 410 | if tutaSucc: 411 | result["Tutanota"] = tutaSucc 412 | 413 | await sreq.close() 414 | 415 | return result 416 | 417 | 418 | async def yahoo(target, req_session_fun, *args, **kwargs) -> Dict: 419 | result = {} 420 | 421 | yahooURL = "https://login.yahoo.com:443/account/module/create?validateField=yid" 422 | yahooCookies = {"B": "10kh9jteu3edn&b=3&s=66", "AS": "v=1&s=wy5fFM96"} # 13 8 423 | # yahooCookies = {"B": "{}&b=3&s=66".format(randstr(13)), "AS": "v=1&s={}".format(randstr(8))} # 13 8 424 | headers = {"User-Agent": random.choice(uaLst), 425 | "Accept": "*/*", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", 426 | "Referer": "https://login.yahoo.com/account/create?.src=ym&.lang=en-US&.intl=us&.done=https%3A%2F%2Fmail.yahoo.com%2Fd&authMechanism=primary&specId=yidReg", 427 | "content-type": "application/x-www-form-urlencoded; charset=UTF-8", "X-Requested-With": "XMLHttpRequest", 428 | "DNT": "1", "Connection": "close"} 429 | 430 | # yahooPOST = {"specId": "yidReg", "crumb": randstr(11), "acrumb": randstr(8), "yid": target} # crumb: 11, acrumb: 8 431 | yahooPOST = {"specId": "yidReg", "crumb": "bshN8x9qmfJ", "acrumb": "wy5fFM96", "yid": target} 432 | sreq = req_session_fun() 433 | 434 | try: 435 | yahooChk = await sreq.post(yahooURL, headers=headers, cookies=yahooCookies, data=yahooPOST, timeout=kwargs.get('timeout', 5)) 436 | 437 | body = await yahooChk.text() 438 | if '"IDENTIFIER_EXISTS"' in body: 439 | result["Yahoo"] = f"{target}@yahoo.com" 440 | 441 | except Exception as e: 442 | logger.error(e, exc_info=True) 443 | 444 | await sreq.close() 445 | 446 | return result 447 | 448 | 449 | async def outlook(target, req_session_fun, *args, **kwargs) -> Dict: 450 | result = {} 451 | liveSucc = [] 452 | sreq = AsyncHTMLSession() 453 | headers = { 454 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:133.0) Gecko/20100101 Firefox/133.0", 455 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 456 | "Accept-Language": "en-US,en;q=0.5", 457 | "Accept-Encoding": "gzip, deflate, br, zstd", 458 | "Upgrade-Insecure-Requests": "1", 459 | "Sec-Fetch-Dest": "document", 460 | "Sec-Fetch-Mode": "navigate", 461 | "Sec-Fetch-Site": "cross-site", 462 | "Priority": "u=0, i", 463 | "Pragma": "no-cache", 464 | "Cache-Control": "no-cache" 465 | } 466 | liveLst = ["outlook.com", "hotmail.com"] 467 | url_template = 'https://signup.live.com/?username={}%40{}&lic=1' 468 | 469 | for maildomain in liveLst: 470 | try: 471 | liveChk = await sreq.get(url_template.format(target, maildomain), headers=headers) 472 | await liveChk.html.arender(sleep=1) 473 | 474 | if "Someone already has this email address" in liveChk.html.html: 475 | liveSucc.append(f"{target}@{maildomain}") 476 | 477 | except Exception as e: 478 | logger.error(e, exc_info=True) 479 | 480 | if liveSucc: 481 | result["Live"] = liveSucc 482 | 483 | await sreq.close() 484 | 485 | return result 486 | 487 | 488 | async def zoho(target, req_session_fun, *args, **kwargs) -> Dict: 489 | result = {} 490 | 491 | headers = { 492 | "User-Agent": "User-Agent: Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.7113.93 Safari/537.36", 493 | "Referer": "https://www.zoho.com/", 494 | "Origin": "https://www.zoho.com" 495 | } 496 | 497 | zohoURL = "https://accounts.zoho.com:443/accounts/validate/register.ac" 498 | zohoPOST = {"username": target, "servicename": "VirtualOffice", "serviceurl": "/"} 499 | sreq = req_session_fun() 500 | 501 | try: 502 | zohoChk = await sreq.post(zohoURL, headers=headers, data=zohoPOST, timeout=kwargs.get('timeout', 10)) 503 | 504 | async with zohoChk: 505 | if zohoChk.status == 200: 506 | # if "IAM.ERROR.USERNAME.NOT.AVAILABLE" in zohoChk.text: 507 | # print("[+] Success with {}@zohomail.com".format(target)) 508 | resp = await zohoChk.json() 509 | if resp['error']['username'] == 'This username is taken': 510 | result["Zoho"] = f"{target}@zohomail.com" 511 | # print("[+] Success with {}@zohomail.com".format(target)) 512 | except Exception as e: 513 | logger.error(e, exc_info=True) 514 | 515 | await sreq.close() 516 | 517 | return result 518 | 519 | 520 | async def lycos(target, req_session_fun, *args, **kwargs) -> Dict: 521 | result = {} 522 | 523 | lycosURL = f"https://registration.lycos.com/usernameassistant.php?validate=1&m_AID=0&t=1625674151843&m_U={target}&m_PR=27&m_SESSIONKEY=4kCL5VaODOZ5M5lBF2lgVONl7tveoX8RKmedGRU3XjV3xRX5MqCP2NWHKynX4YL4" 524 | 525 | 526 | headers = { 527 | "User-Agent": "User-Agent: Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.7113.93 Safari/537.36", 528 | "Referer": "https://registration.lycos.com/register.php?m_PR=27&m_E=7za1N6E_h_nNSmIgtfuaBdmGpbS66MYX7lMDD-k9qlZCyq53gFjU_N12yVxL01F0R_mmNdhfpwSN6Kq6bNfiqQAA", 529 | "X-Requested-With": "XMLHttpRequest"} 530 | sreq = req_session_fun() 531 | 532 | try: 533 | lycosChk = await sreq.get(lycosURL, headers=headers, timeout=kwargs.get('timeout', 10)) 534 | 535 | async with lycosChk: 536 | if lycosChk.status == 200: 537 | resp = await lycosChk.text() 538 | if resp == "Unavailable": 539 | result["Lycos"] = f"{target}@lycos.com" 540 | except Exception as e: 541 | logger.error(e, exc_info=True) 542 | 543 | await sreq.close() 544 | 545 | return result 546 | 547 | 548 | async def eclipso(target, req_session_fun, *args, **kwargs) -> Dict: # high ban risk + false positives after 549 | result = {} 550 | 551 | eclipsoSucc = [] 552 | 553 | eclipsoLst = ["eclipso.eu", 554 | "eclipso.de", 555 | "eclipso.at", 556 | "eclipso.ch", 557 | "eclipso.be", 558 | "eclipso.es", 559 | "eclipso.it", 560 | "eclipso.me", 561 | "eclipso.nl", 562 | "eclipso.email"] 563 | 564 | headers = {'User-Agent': random.choice(uaLst), 565 | 'Referer': 'https://www.eclipso.eu/signup/tariff-5', 566 | 'X-Requested-With': 'XMLHttpRequest'} 567 | sreq = req_session_fun() 568 | 569 | for maildomain in eclipsoLst: 570 | try: 571 | targetMail = f"{target}@{maildomain}" 572 | 573 | eclipsoURL = f"https://www.eclipso.eu/index.php?action=checkAddressAvailability&address={targetMail}" 574 | 575 | chkEclipso = await sreq.get(eclipsoURL, headers=headers, timeout=kwargs.get('timeout', 5)) 576 | 577 | async with chkEclipso: 578 | if chkEclipso.status == 200: 579 | resp = await chkEclipso.text() 580 | if '>0<' in resp: 581 | eclipsoSucc.append(targetMail) 582 | except Exception as e: 583 | logger.error(e, exc_info=True) 584 | 585 | await asyncio.sleep(random.uniform(2, 4)) 586 | 587 | if eclipsoSucc: 588 | result["Eclipso"] = eclipsoSucc 589 | 590 | await sreq.close() 591 | 592 | return result 593 | 594 | 595 | async def posteo(target, req_session_fun, *args, **kwargs) -> Dict: 596 | result = {} 597 | 598 | posteoLst = [ 599 | "posteo.af", 600 | "posteo.at", 601 | "posteo.be", 602 | "posteo.ca", 603 | "posteo.ch", 604 | "posteo.cl", 605 | "posteo.co", 606 | "posteo.co.uk", 607 | "posteo.com.br", 608 | "posteo.cr", 609 | "posteo.cz", 610 | "posteo.de", 611 | "posteo.dk", 612 | "posteo.ee", 613 | "posteo.es", 614 | "posteo.eu", 615 | "posteo.fi", 616 | "posteo.gl", 617 | "posteo.gr", 618 | "posteo.hn", 619 | "posteo.hr", 620 | "posteo.hu", 621 | "posteo.ie", 622 | "posteo.in", 623 | "posteo.is", 624 | "posteo.it", 625 | "posteo.jp", 626 | "posteo.la", 627 | "posteo.li", 628 | "posteo.lt", 629 | "posteo.lu", 630 | "posteo.me", 631 | "posteo.mx", 632 | "posteo.my", 633 | "posteo.net", 634 | "posteo.nl", 635 | "posteo.no", 636 | "posteo.nz", 637 | "posteo.org", 638 | "posteo.pe", 639 | "posteo.pl", 640 | "posteo.pm", 641 | "posteo.pt", 642 | "posteo.ro", 643 | "posteo.ru", 644 | "posteo.se", 645 | "posteo.sg", 646 | "posteo.si", 647 | "posteo.tn", 648 | "posteo.uk", 649 | "posteo.us"] 650 | 651 | headers = { 652 | 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36', 653 | 'Referer': 'https://posteo.de/en/signup', 654 | 'X-Requested-With': 'XMLHttpRequest'} 655 | 656 | sreq = req_session_fun() 657 | try: 658 | posteoURL = f"https://posteo.de/users/new/check_username?user%5Busername%5D={target}" 659 | 660 | chkPosteo = await sreq.get(posteoURL, headers=headers, timeout=kwargs.get('timeout', 5)) 661 | 662 | async with chkPosteo: 663 | if chkPosteo.status == 200: 664 | resp = await chkPosteo.text() 665 | if resp == "false": 666 | result["Posteo"] = [ 667 | f"{target}@posteo.net", 668 | "~50 aliases: https://posteo.de/en/help/which-domains-are-available-to-use-as-a-posteo-alias-address", 669 | ] 670 | 671 | except Exception as e: 672 | logger.error(e, exc_info=True) 673 | 674 | await sreq.close() 675 | 676 | return result 677 | 678 | 679 | async def mailbox(target, req_session_fun, *args, **kwargs) -> Dict: # tor RU 680 | result = {} 681 | 682 | mailboxURL = "https://register.mailbox.org:443/ajax" 683 | headers = { 684 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36"} 685 | mailboxJSON = {"account_name": target, "action": "validateAccountName"} 686 | 687 | existiert = "Der Accountname existiert bereits." 688 | sreq = req_session_fun() 689 | 690 | try: 691 | chkMailbox = await sreq.post(mailboxURL, headers=headers, json=mailboxJSON, timeout=kwargs.get('timeout', 10)) 692 | 693 | async with chkMailbox: 694 | resp = await chkMailbox.text() 695 | if resp == existiert: 696 | result["MailBox"] = f"{target}@mailbox.org" 697 | except Exception as e: 698 | logger.error(e, exc_info=True) 699 | 700 | await sreq.close() 701 | 702 | return result 703 | 704 | 705 | async def firemail(target, req_session_fun, *args, **kwargs) -> Dict: # tor RU 706 | result = {} 707 | 708 | firemailSucc = [] 709 | 710 | firemailDomains = ["firemail.at", "firemail.de", "firemail.eu"] 711 | 712 | headers = {'User-Agent': random.choice(uaLst), 713 | 'Referer': 'https://firemail.de/E-Mail-Adresse-anmelden', 714 | 'X-Requested-With': 'XMLHttpRequest'} 715 | sreq = req_session_fun() 716 | 717 | for firemailDomain in firemailDomains: 718 | try: 719 | targetMail = f"{target}@{firemailDomain}" 720 | 721 | firemailURL = f"https://firemail.de/index.php?action=checkAddressAvailability&address={targetMail}" 722 | 723 | chkFiremail = await sreq.get(firemailURL, headers=headers, timeout=kwargs.get('timeout', 10)) 724 | 725 | async with chkFiremail: 726 | if chkFiremail.status == 200: 727 | resp = await chkFiremail.text() 728 | if '>0<' in resp: 729 | firemailSucc.append(f"{targetMail}") 730 | except Exception as e: 731 | logger.error(e, exc_info=True) 732 | 733 | await asyncio.sleep(random.uniform(2, 4)) 734 | 735 | if firemailSucc: 736 | result["Firemail"] = firemailSucc 737 | 738 | await sreq.close() 739 | 740 | return result 741 | 742 | 743 | async def fastmail(target, req_session_fun, *args, **kwargs) -> Dict: # sanctions against Russia) TOR + 4 min for check in loop( 744 | result = {} 745 | 746 | # Registration form on fastmail website automatically lowercase all input. 747 | # If uppercase letters are used false positive results are returned. 748 | target = target.lower() 749 | 750 | # validate target syntax to prevent false positive results 751 | match = re.search(r'^[a-zA-Z]\w{2,40}$', target, re.ASCII) 752 | 753 | if not match: 754 | return result 755 | 756 | fastmailSucc = [] 757 | 758 | fastmailLst = [ 759 | "fastmail.com", "fastmail.cn", "fastmail.co.uk", "fastmail.com.au", 760 | "fastmail.de", "fastmail.es", "fastmail.fm", "fastmail.fr", 761 | "fastmail.im", "fastmail.in", "fastmail.jp", "fastmail.mx", 762 | "fastmail.net", "fastmail.nl", "fastmail.org", "fastmail.se", 763 | "fastmail.to", "fastmail.tw", "fastmail.uk", "fastmail.us", 764 | "123mail.org", "airpost.net", "eml.cc", "fmail.co.uk", 765 | "fmgirl.com", "fmguy.com", "mailbolt.com", "mailcan.com", 766 | "mailhaven.com", "mailmight.com", "ml1.net", "mm.st", 767 | "myfastmail.com", "proinbox.com", "promessage.com", "rushpost.com", 768 | "sent.as", "sent.at", "sent.com", "speedymail.org", 769 | "warpmail.net", "xsmail.com", "150mail.com", "150ml.com", 770 | "16mail.com", "2-mail.com", "4email.net", "50mail.com", 771 | "allmail.net", "bestmail.us", "cluemail.com", "elitemail.org", 772 | "emailcorner.net", "emailengine.net", "emailengine.org", "emailgroups.net", 773 | "emailplus.org", "emailuser.net", "f-m.fm", "fast-email.com", 774 | "fast-mail.org", "fastem.com", "fastemail.us", "fastemailer.com", 775 | "fastest.cc", "fastimap.com", "fastmailbox.net", "fastmessaging.com", 776 | "fea.st", "fmailbox.com", "ftml.net", "h-mail.us", 777 | "hailmail.net", "imap-mail.com", "imap.cc", "imapmail.org", 778 | "inoutbox.com", "internet-e-mail.com", "internet-mail.org", 779 | "internetemails.net", "internetmailing.net", "jetemail.net", 780 | "justemail.net", "letterboxes.org", "mail-central.com", "mail-page.com", 781 | "mailandftp.com", "mailas.com", "mailc.net", "mailforce.net", 782 | "mailftp.com", "mailingaddress.org", "mailite.com", "mailnew.com", 783 | "mailsent.net", "mailservice.ms", "mailup.net", "mailworks.org", 784 | "mymacmail.com", "nospammail.net", "ownmail.net", "petml.com", 785 | "postinbox.com", "postpro.net", "realemail.net", "reallyfast.biz", 786 | "reallyfast.info", "speedpost.net", "ssl-mail.com", "swift-mail.com", 787 | "the-fastest.net", "the-quickest.com", "theinternetemail.com", 788 | "veryfast.biz", "veryspeedy.net", "yepmail.net", "your-mail.com"] 789 | 790 | headers = {"User-Agent": random.choice(uaLst), 791 | "Referer": "https://www.fastmail.com/signup/", 792 | "Content-type": "application/json", 793 | "X-TrustedClient": "Yes", 794 | "Origin": "https://www.fastmail.com"} 795 | 796 | fastmailURL = "https://www.fastmail.com:443/jmap/setup/" 797 | sreq = req_session_fun() 798 | 799 | for fmdomain in fastmailLst: 800 | # print(fastmailLst.index(fmdomain)+1, fmdomain) 801 | 802 | fmmail = f"{target}@{fmdomain}" 803 | 804 | fastmailJSON = {"methodCalls": [["Signup/getEmailAvailability", {"email": fmmail}, "0"]], 805 | "using": ["https://www.fastmail.com/dev/signup"]} 806 | 807 | try: 808 | chkFastmail = await sreq.post(fastmailURL, headers=headers, json=fastmailJSON, timeout=kwargs.get('timeout', 5)) 809 | 810 | async with chkFastmail: 811 | if chkFastmail.status == 200: 812 | resp = await chkFastmail.json() 813 | fmJson = resp['methodResponses'][0][1]['isAvailable'] 814 | if fmJson is False: 815 | fastmailSucc.append(f"{fmmail}") 816 | 817 | except Exception as e: 818 | logger.error(e, exc_info=True) 819 | 820 | await asyncio.sleep(random.uniform(0.5, 1.1)) 821 | 822 | if fastmailSucc: 823 | result["Fastmail"] = fastmailSucc 824 | 825 | await sreq.close() 826 | 827 | return result 828 | 829 | 830 | async def startmail(target, req_session_fun, *args, **kwargs) -> Dict: # TOR 831 | result = {} 832 | 833 | startmailURL = f"https://mail.startmail.com:443/api/AvailableAddresses/{target}%40startmail.com" 834 | 835 | headers = {"User-Agent": random.choice(uaLst), 836 | "X-Requested-With": "1.94.0"} 837 | sreq = req_session_fun() 838 | 839 | try: 840 | chkStartmail = await sreq.get(startmailURL, headers=headers, timeout=kwargs.get('timeout', 10)) 841 | 842 | async with chkStartmail: 843 | if chkStartmail.status == 404: 844 | result["StartMail"] = f"{target}@startmail.com" 845 | 846 | except Exception as e: 847 | logger.error(e, exc_info=True) 848 | 849 | await sreq.close() 850 | 851 | return result 852 | 853 | 854 | async def kolab(target, req_session_fun, *args, **kwargs) -> Dict: 855 | result: Dict[str, List] = {} 856 | 857 | kolabLst = ["mykolab.com", 858 | "attorneymail.ch", 859 | "barmail.ch", 860 | "collaborative.li", 861 | "diplomail.ch", 862 | "freedommail.ch", 863 | "groupoffice.ch", 864 | "journalistmail.ch", 865 | "legalprivilege.ch", 866 | "libertymail.co", 867 | "libertymail.net", 868 | "mailatlaw.ch", 869 | "medicmail.ch", 870 | "medmail.ch", 871 | "mykolab.ch", 872 | "myswissmail.ch", 873 | "opengroupware.ch", 874 | "pressmail.ch", 875 | "swisscollab.ch", 876 | "swissgroupware.ch", 877 | "switzerlandmail.ch", 878 | "trusted-legal-mail.ch", 879 | "kolabnow.com", 880 | "kolabnow.ch"] 881 | 882 | ''' # old cool version ;( 883 | kolabURL = "https://kolabnow.com:443/cockpit/json.php" 884 | headers = { "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0", 885 | "Referer": "https://kolabnow.com/cockpit/signup/individual", 886 | "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", 887 | "X-Requested-With": "XMLHttpRequest"} 888 | 889 | try: 890 | kolabStatus = sreq.post(kolabURL, headers=headers) 891 | print(kolabStatus.status_code) 892 | 893 | if kolabStatus.status_code == 200: 894 | 895 | for kolabdomain in kolabLst: 896 | 897 | kolabPOST = {"validate": "username", 898 | "accounttype": "individual", 899 | "username": target, 900 | "domain": kolabdomain, 901 | "_action_": "/signup/validate"} 902 | 903 | try: 904 | 905 | chkKolab = sreq.post(kolabURL, headers=headers, data=kolabPOST) 906 | 907 | if chkKolab.status_code == 200: 908 | 909 | kolabJSON = chkKolab.json() 910 | 911 | if kolabJSON['errors']: 912 | suc = "This email address is not available" 913 | if kolabJSON['errors']['username'] == suc: 914 | print("[+] Success with {}@{}".format(target, kolabdomain)) 915 | 916 | except Exception as e: 917 | pass 918 | 919 | sleep(random.uniform(1, 3)) 920 | 921 | except Exception as e: 922 | #pass 923 | print e 924 | ''' 925 | 926 | kolabURL = "https://kolabnow.com/api/auth/signup" 927 | headers = {"User-Agent": random.choice(uaLst), 928 | "Referer": "https://kolabnow.com/signup/individual", 929 | "Content-Type": "application/json;charset=utf-8", 930 | "X-Test-Payment-Provider": "mollie", 931 | "X-Requested-With": "XMLHttpRequest"} 932 | sreq = req_session_fun() 933 | timeout = kwargs.get('timeout', 10) 934 | 935 | kolabStatus = await sreq.post(kolabURL, headers={"User-Agent": random.choice(uaLst)}, timeout=timeout) 936 | 937 | if kolabStatus.status == 422: 938 | 939 | kolabpass = randstr(12) 940 | kolabsuc = "The specified login is not available." 941 | 942 | for kolabdomain in kolabLst: 943 | 944 | kolabPOST = {"login": target, 945 | "domain": kolabdomain, 946 | "password": kolabpass, 947 | "password_confirmation": kolabpass, 948 | "voucher": "", 949 | "code": "bJDmpWw8sO85KlgSETPWtnViDgQ1S0MO", 950 | "short_code": "VHBZX"} 951 | 952 | try: 953 | # chkKolab = sreq.post(kolabURL, headers=headers, data=kolabPOST) 954 | chkKolab = await sreq.post(kolabURL, headers=headers, data=json.dumps(kolabPOST), timeout=timeout) 955 | resp = await chkKolab.text() 956 | 957 | if chkKolab.status == 200: 958 | 959 | kolabJSON = chkKolab.json() 960 | if ( 961 | kolabJSON["errors"]["login"] != kolabsuc 962 | and kolabJSON["errors"] 963 | ): 964 | print(kolabJSON["errors"]) 965 | 966 | except Exception as e: 967 | logger.error(e, exc_info=True) 968 | 969 | await sreq.close() 970 | 971 | return result 972 | 973 | 974 | async def bigmir(target, req_session_fun, *args, **kwargs) -> Dict: 975 | result = {} 976 | 977 | bigmirSucc = [] 978 | bigmirMail = ["i.ua", "ua.fm", "email.ua"] 979 | sreq = req_session_fun() 980 | 981 | for maildomain in bigmirMail: 982 | try: 983 | bigmirChkJS = "https://passport.i.ua/js/free.js?15908746259240-xml" 984 | 985 | headers = { 986 | 'Pragma': 'no-cache', 987 | 'Origin': 'https://passport.i.ua', 988 | 'User-Agent': random.choice(uaLst), 989 | 'Content-Type': 'application/octet-stream', 990 | 'Referer': 'https://passport.i.ua/registration/' 991 | } 992 | 993 | bm_data = f"login={target}@{maildomain}" 994 | 995 | bigmirChk = await sreq.post(bigmirChkJS, headers=headers, data=bm_data, timeout=kwargs.get('timeout', 10)) 996 | 997 | async with bigmirChk: 998 | if bigmirChk.status == 200: 999 | exist = "'free': false" 1000 | 1001 | resp = await bigmirChk.text() 1002 | if "'free': false" in resp: 1003 | bigmirSucc.append(f"{target}@{maildomain}") 1004 | 1005 | await asyncio.sleep(random.uniform(2, 4)) 1006 | 1007 | except Exception as e: 1008 | logger.error(e, exc_info=True) 1009 | 1010 | if bigmirSucc: 1011 | result["Bigmir"] = bigmirSucc 1012 | 1013 | await sreq.close() 1014 | 1015 | return result 1016 | 1017 | 1018 | 1019 | async def xmail(target, req_session_fun, *args, **kwargs) -> Dict: 1020 | result = {} 1021 | 1022 | sreq = req_session_fun() 1023 | xmailURL = "https://xmail.net:443/app/signup/checkusername" 1024 | headers = {"User-Agent": random.choice(uaLst), 1025 | "Accept": "application/json, text/javascript, */*", 1026 | "Referer": "https://xmail.net/app/signup", 1027 | "Content-Type": "application/x-www-form-urlencoded", 1028 | "X-Requested-With": "XMLHttpRequest", 1029 | "Connection": "close"} 1030 | 1031 | xmailPOST = {"username": target, "firstname": '', "lastname": ''} 1032 | 1033 | try: 1034 | xmailChk = await sreq.post(xmailURL, headers=headers, data=xmailPOST, timeout=kwargs.get('timeout', 10)) 1035 | 1036 | async with xmailChk: 1037 | resp = await xmailChk.json() 1038 | if not resp['username']: 1039 | result["Xmail"] = f"{target}@xmail.net" 1040 | 1041 | except Exception as e: 1042 | logger.error(e, exc_info=True) 1043 | 1044 | await sreq.close() 1045 | 1046 | return result 1047 | 1048 | 1049 | async def ukrnet(target, req_session_fun, *args, **kwargs) -> Dict: 1050 | result = {} 1051 | 1052 | ukrnet_reg_urk = "https://accounts.ukr.net:443/registration" 1053 | headers = { 1054 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36", 1055 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 1056 | "Accept-Language": "en-US,en;q=0.5", 1057 | "Accept-Encoding": "gzip, deflate", 1058 | "DNT": "1", 1059 | "Connection": "close", 1060 | "Upgrade-Insecure-Requests": "1"} 1061 | 1062 | sreq = req_session_fun() 1063 | timeout = kwargs.get('timeout', 10) 1064 | 1065 | try: 1066 | 1067 | get_reg_ukrnet = await sreq.get(ukrnet_reg_urk, headers=headers, timeout=timeout) 1068 | 1069 | async with get_reg_ukrnet: 1070 | if get_reg_ukrnet.status == 200: 1071 | if ukrnet_cookies := sreq.cookie_jar: 1072 | ukrnetURL = "https://accounts.ukr.net:443/api/v1/registration/reserve_login" 1073 | ukrnetPOST = {"login": target} 1074 | 1075 | ukrnetChk = await sreq.post(ukrnetURL, headers=headers, json=ukrnetPOST, timeout=timeout) 1076 | 1077 | async with ukrnetChk: 1078 | if ukrnetChk.status == 200: 1079 | resp = await ukrnetChk.json() 1080 | if not resp['available']: 1081 | result["UkrNet"] = f"{target}@ukr.net" 1082 | except Exception as e: 1083 | logger.error(e, exc_info=True) 1084 | 1085 | await sreq.close() 1086 | 1087 | return result 1088 | 1089 | 1090 | async def runbox(target, req_session_fun, *args, **kwargs) -> Dict: 1091 | result = {} 1092 | 1093 | runboxSucc = [] 1094 | runboxLst = ["mailhost.work", 1095 | "mailhouse.biz", 1096 | "messagebox.email", 1097 | "offshore.rocks", 1098 | "rbox.co", 1099 | "rbox.me", 1100 | "rbx.email", 1101 | "rbx.life", 1102 | "rbx.run", 1103 | "rnbx.uk", 1104 | "runbox.at", 1105 | "runbox.biz", 1106 | "runbox.bz", 1107 | "runbox.ch", 1108 | "runbox.co", 1109 | "runbox.co.in", 1110 | "runbox.com", 1111 | "runbox.dk", 1112 | "runbox.email", 1113 | "runbox.eu", 1114 | "runbox.is", 1115 | "runbox.it", 1116 | "runbox.ky", 1117 | "runbox.li", 1118 | "runbox.me", 1119 | "runbox.nl", 1120 | "runbox.no", 1121 | "runbox.uk", 1122 | "runbox.us", 1123 | "xobnur.uk"] 1124 | 1125 | headers = {"User-Agent": random.choice(uaLst), 1126 | "Origin": "https://runbox.com", 1127 | "Referer": "https://runbox.com/signup?runbox7=1"} 1128 | 1129 | sreq = req_session_fun() 1130 | for rboxdomain in runboxLst: 1131 | try: 1132 | data = {"type": "person", "company": "", "first_name": "", "last_name": "", "user": target, 1133 | "userdomain": "domainyouown.com", "runboxDomain": rboxdomain, "password": "", 1134 | "password_strength": "", "email_alternative": "", "phone_number_cellular": "", 1135 | "referrer": "", "phone_number_home": "", "g-recaptcha-response": "", 1136 | "h-captcha-response": "", "signup": "%A0Set+up+my+Runbox+account%A0", 1137 | "av": "y", "as": "y", "domain": "", "accountType": "person", "domainType": "runbox", 1138 | "account_number": "", "timezone": "undefined", "runbox7": "1"} 1139 | 1140 | chkRunbox = await sreq.post('https://runbox.com/signup/signup', headers=headers, data=data, timeout=kwargs.get('timeout', 5)) 1141 | 1142 | if chkRunbox.status == 200: 1143 | resp = await chkRunbox.text() 1144 | if "The specified username is already taken" in resp: 1145 | runboxSucc.append(f"{target}@{rboxdomain}") 1146 | 1147 | except Exception as e: 1148 | logger.error(e, exc_info=True) 1149 | 1150 | finally: 1151 | await asyncio.sleep(random.uniform(1, 2.1)) 1152 | 1153 | if runboxSucc: 1154 | result["Runbox"] = runboxSucc 1155 | 1156 | await sreq.close() 1157 | 1158 | return result 1159 | 1160 | 1161 | async def iCloud(target, req_session_fun, *args, **kwargs) -> Dict: 1162 | result: Dict[str, List] = {} 1163 | 1164 | domains = [ 1165 | 'icloud.com', 1166 | 'me.com', 1167 | 'mac.com', 1168 | ] 1169 | 1170 | sreq = req_session_fun() 1171 | timeout= kwargs.get('timeout', 5) 1172 | 1173 | for domain in domains: 1174 | try: 1175 | email = f'{target}@{domain}' 1176 | headers = { 1177 | 'User-Agent': random.choice(uaLst), 1178 | 'sstt': 'zYEaY3WeI76oAG%2BCNPhCiGcKUCU0SIQ1cIO2EMepSo8egjarh4MvVPqxGOO20TYqlbJI%2Fqs57WwAoJarOPukJGJvgOF7I7C%2B1jAE5vZo%2FSmYkvi2e%2Bfxj1od1xJOf3lnUXZlrnL0QWpLfaOgOwjvorSMJ1iuUphB8bDqjRzyb76jzDU4hrm6TzkvxJdlPCCY3JVTfAZFgXRoW9VlD%2Bv3VF3in1RSf6Er2sOS12%2FZJR%2Buo9ubA2KH9RLRzPlr1ABtsRgw6r4zbFbORaKTSVWGDQPdYCaMsM4ebevyKj3aIxXa%2FOpS6SHcx1KrvtOAUVhR9nsfZsaYfZvDa6gzpcNBF9domZJ1p8MmThEfJra6LEuc9ssZ3aWn9uKqvT3pZIVIbgdZARL%2B6SK1YCN7', 1179 | 'Content-Type': 'application/json', 1180 | } 1181 | 1182 | data = {'id': email} 1183 | check = await sreq.post('https://iforgot.apple.com/password/verify/appleid', 1184 | headers=headers, data=json.dumps(data), 1185 | allow_redirects=False, 1186 | timeout=timeout 1187 | ) 1188 | if check.headers and check.headers.get('Location', '').startswith('/password/authenticationmethod'): 1189 | if not result: 1190 | result = {'iCloud': []} 1191 | result['iCloud'].append(email) 1192 | except Exception as e: 1193 | logger.error(e, exc_info=True) 1194 | 1195 | await sreq.close() 1196 | 1197 | return result 1198 | 1199 | 1200 | async def duckgo(target, req_session_fun, *args, **kwargs) -> Dict: 1201 | result = {} 1202 | 1203 | duckURL = "https://quack.duckduckgo.com/api/auth/signup" 1204 | 1205 | headers = {"User-Agent": random.choice(uaLst), "Origin": "https://duckduckgo.com", "Sec-Fetch-Dest": "empty", 1206 | "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-site", "Te": "trailers", "Referer": "https://duckduckgo.com/"} 1207 | 1208 | data = { 1209 | "code": (None, "01337"), 1210 | "user": (None, target), 1211 | "email": (None, "mail@example.com") 1212 | 1213 | } 1214 | 1215 | sreq = req_session_fun() 1216 | 1217 | try: 1218 | checkDuck = await sreq.post(duckURL, headers=headers, data=data, timeout=kwargs.get('timeout', 5)) 1219 | 1220 | resp = await checkDuck.text() 1221 | # if checkDuck.json()['error'] == "unavailable_username": 1222 | if "unavailable_username" in resp: 1223 | result["DuckGo"] = f"{target}@duck.com" 1224 | 1225 | except Exception as e: 1226 | logger.error(e, exc_info=True) 1227 | 1228 | await sreq.close() 1229 | 1230 | return result 1231 | 1232 | 1233 | async def ctemplar(target, req_session_fun, *args, **kwargs) -> Dict: 1234 | 1235 | result = {} 1236 | 1237 | # validate target syntax to prevent false positive results (e.g. no dot at the end of target allowed) 1238 | match = re.search(r'^[a-zA-Z][\w\-.]{2,}[a-zA-Z\d]$', target) 1239 | 1240 | if not match: 1241 | return result 1242 | 1243 | sreq = req_session_fun() 1244 | 1245 | ctURL = "https://api.ctemplar.com/auth/check-username/" 1246 | ctJSON = {"username": target} 1247 | 1248 | headers = {"User-Agent": random.choice(uaLst), 1249 | "Accept": "application/json, text/plain, */*", 1250 | "Referer": "https://mail.ctemplar.com/", 1251 | "Content-Type": "application/json", 1252 | "Origin": "https://mail.ctemplar.com"} 1253 | 1254 | try: 1255 | chkCT = await sreq.post(ctURL, headers=headers, json=ctJSON) 1256 | 1257 | if chkCT.status == 200: 1258 | resp = await chkCT.json() 1259 | if ct_exists := resp['exists']: 1260 | result["CTemplar"] = f"{target}@ctemplar.com" 1261 | 1262 | except Exception as e: 1263 | logger.error(e, exc_info=True) 1264 | 1265 | await sreq.close() 1266 | 1267 | return result 1268 | 1269 | 1270 | async def hushmail(target, req_session_fun, *args, **kwargs) -> Dict: 1271 | 1272 | result = {} 1273 | 1274 | hushDomains = ["hushmail.com", "hush.com", "therapyemail.com", "counselingmail.com", "therapysecure.com", "counselingsecure.com"] 1275 | hushSucc = [] 1276 | sreq = req_session_fun() 1277 | 1278 | hush_ts = int(datetime.datetime.now().timestamp()) 1279 | 1280 | hushURL = "https://secure.hushmail.com/signup/create?format=json" 1281 | ref_header = "https://secure.hushmail.com/signup/?package=hushmail-for-healthcare-individual-5-form-monthly&source=website&tag=page_business_healthcare,btn_healthcare_popup_signup_individual&coupon_code=" 1282 | hush_UA = random.choice(uaLst) 1283 | 1284 | hushpass = randstr(15) 1285 | 1286 | for hushdomain in hushDomains: 1287 | 1288 | # hushpass = randstr(15) 1289 | hush_ts = int(datetime.datetime.now().timestamp()) 1290 | 1291 | headers = {"User-Agent": hush_UA, 1292 | "Accept": "application/json, text/javascript, */*; q=0.01", 1293 | "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", 1294 | "X-Hush-Ajax-Start-Time": str(hush_ts), "X-Requested-With": "XMLHttpRequest", 1295 | "Origin": "https://secure.hushmail.com", "Referer": ref_header, 1296 | "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-origin"} 1297 | 1298 | data = {"hush_customerid": '', "hush_exitmethod": "GET", 1299 | "skin": "bootstrap311", "hush_cc_country": '', 1300 | "trial_mode": '', "parent": '', "parent_code": '', 1301 | "coupon_code": '', "form_token": "6e1555a603f6e762a090e6f6b885122f_dabaddeadbee", 1302 | "__hushform_extra_fields": '', "hush_username": target, "hush_domain": hushdomain, 1303 | "hush_pass1": hushpass, "hush_pass2": hushpass, 1304 | "hush_exitpage": "https://secure.hushmail.com/pay?package=hushmail-for-healthcare-individual-5-form-monthly", 1305 | "package": "hushmail-for-healthcare-individual-5-form-monthly", 1306 | "hush_reservation_code": '', "hush_customerid": '', "hush_tos": '', "hush_privacy_policy": '', 1307 | "hush_additional_tos": '', "hush_email_opt_in": '', "isValidAjax": "newaccountform"} 1308 | 1309 | try: 1310 | hushCheck = await sreq.post(hushURL, headers=headers, data=data, timeout=kwargs.get('timeout', 5)) 1311 | 1312 | if hushCheck.status == 200: 1313 | resp = await hushCheck.json() 1314 | if ( 1315 | f"'{target}' is not available" 1316 | in resp['formValidation']['hush_username'] 1317 | ): 1318 | hushMail = f"{target}@{hushdomain}" 1319 | hushSucc.append(hushMail) 1320 | 1321 | except Exception as e: 1322 | logger.error(e, exc_info=True) 1323 | 1324 | await sleeper(hushDomains, 1.1, 2.2) 1325 | 1326 | if hushSucc: 1327 | result["HushMail"] = hushSucc 1328 | 1329 | await sreq.close() 1330 | 1331 | return result 1332 | 1333 | 1334 | async def emailn(target, req_session_fun, *args, **kwargs) -> Dict: 1335 | result = {} 1336 | 1337 | emailnURL = f"https://www.emailn.de/webmail/index.php?action=checkAddressAvailability&address={target}@emailn.de" 1338 | 1339 | headers = {'User-Agent': random.choice(uaLst)} 1340 | sreq = req_session_fun() 1341 | 1342 | try: 1343 | emailnChk = await sreq.get(emailnURL, headers=headers, timeout=10) 1344 | 1345 | async with emailnChk: 1346 | if emailnChk.status == 200: 1347 | resp = await emailnChk.text() 1348 | if ">0<" in resp: 1349 | result["emailn"] = f"{target}@emailn.de" 1350 | except Exception as e: 1351 | logger.error(e, exc_info=True) 1352 | 1353 | await sreq.close() 1354 | 1355 | return result 1356 | 1357 | 1358 | async def aikq(target, req_session_fun, *args, **kwargs) -> Dict: 1359 | result = {} 1360 | aikqSucc = [] 1361 | 1362 | aikqLst = ["aikq.com", 1363 | "aikq.co", 1364 | "aikq.eu", 1365 | "aikq.de", 1366 | "mails.eu", 1367 | "aikq.net", 1368 | "aikq.org", 1369 | "aikq.biz", 1370 | "aikq.tv", 1371 | "aikq.at", 1372 | "aikq.uk", 1373 | "aikq.co.uk", 1374 | "aikq.fr", 1375 | "aikq.be", 1376 | "aikq.pl", 1377 | "aikq.email", 1378 | "aikq.info", 1379 | "mailbox.info", 1380 | "mails.info", 1381 | "aikq.cloud", 1382 | "aikq.chat", 1383 | "aikq.name", 1384 | "aikq.wiki", 1385 | "aikq.ae", 1386 | "aikq.asia", 1387 | "aikq.by", 1388 | "aikq.com.br", 1389 | "aikq.cz", 1390 | "aikq.ie", 1391 | "aikq.in", 1392 | "aikq.jp", 1393 | "aikq.li", 1394 | "aikq.me", 1395 | "aikq.mx", 1396 | "aikq.nl", 1397 | "aikq.nz", 1398 | "aikq.qa", 1399 | "aikq.sk", 1400 | "aikq.tw", 1401 | "aikq.us", 1402 | "aikq.ws"] 1403 | 1404 | 1405 | headers = {'User-Agent': random.choice(uaLst)} 1406 | sreq = req_session_fun() 1407 | 1408 | for maildomain in aikqLst: 1409 | try: 1410 | targetMail = f"{target}@{maildomain}" 1411 | aikqUrl = f"https://www.aikq.de/index.php?action=checkAddressAvailability&address={targetMail}" 1412 | 1413 | chkAikq = await sreq.get(aikqUrl, headers=headers, timeout=kwargs.get('timeout', 5)) 1414 | 1415 | async with chkAikq: 1416 | if chkAikq.status == 200: 1417 | resp = await chkAikq.text() 1418 | if '>0<' in resp: 1419 | aikqSucc.append(targetMail) 1420 | except Exception as e: 1421 | logger.error(e, exc_info=True) 1422 | 1423 | await asyncio.sleep(random.uniform(2, 4)) 1424 | 1425 | if aikqSucc: 1426 | result["Aikq"] = aikqSucc 1427 | 1428 | await sreq.close() 1429 | 1430 | return result 1431 | 1432 | 1433 | async def vivaldi(target, req_session_fun, *args, **kwargs) -> Dict: 1434 | result = {} 1435 | 1436 | vivaldiURL = "https://login.vivaldi.net:443/profile/validateField" 1437 | headers = { 1438 | "User-Agent": random.choice(uaLst), 1439 | "Content-Type": "application/x-www-form-urlencoded", 1440 | "Origin": "https://login.vivaldi.net", 1441 | "Referer": "https://login.vivaldi.net/profile/id/signup" 1442 | } 1443 | 1444 | vivaldiPOST = {"field": "username", "value": target} 1445 | 1446 | sreq = req_session_fun() 1447 | 1448 | try: 1449 | vivaldiChk = await sreq.post(vivaldiURL, headers=headers, data=vivaldiPOST, timeout=kwargs.get('timeout', 5)) 1450 | 1451 | body = await vivaldiChk.json(content_type=None) 1452 | 1453 | if 'error' in body and body['error'] == "User exists [1007]": 1454 | result["Vivaldi"] = f"{target}@vivaldi.net" 1455 | 1456 | except Exception as e: 1457 | logger.error(e, exc_info=True) 1458 | 1459 | await sreq.close() 1460 | 1461 | return result 1462 | 1463 | async def mailDe(target, req_session_fun, *args, **kwargs) -> Dict: 1464 | result = {} 1465 | mailChkLst, error = await code250("mail.de", target, kwargs.get('timeout', 10)) 1466 | if mailChkLst: 1467 | result["mail.de"] = mailChkLst[0] 1468 | await asyncio.sleep(0) 1469 | return result, error 1470 | 1471 | async def wp(target, req_session_fun, *args, **kwargs) -> Dict: 1472 | result = {} 1473 | 1474 | wpURL = "https://poczta.wp.pl/api/v1/public/registration/accounts/availability" 1475 | headers = { 1476 | "User-Agent": random.choice(uaLst), 1477 | "Content-Type": "application/json;charset=UTF-8", 1478 | "Origin": "https://poczta.wp.pl", 1479 | "Referer": "https://poczta.wp.pl/rejestracja/", 1480 | "Accept": "application/json" 1481 | } 1482 | 1483 | data = f'{{"login":"{target}"}}' 1484 | 1485 | sreq = req_session_fun() 1486 | 1487 | try: 1488 | wpChk = await sreq.put(wpURL, headers=headers, data=data, timeout=kwargs.get('timeout', 5)) 1489 | 1490 | body = await wpChk.json(content_type=None) 1491 | 1492 | if "Podany login jest niedostępny." in str(body): 1493 | result["Wirtualna Polska"] = f"{target}@wp.pl" 1494 | 1495 | except Exception as e: 1496 | logger.error(e, exc_info=True) 1497 | 1498 | await sreq.close() 1499 | 1500 | return result 1501 | 1502 | async def gazeta(target, req_session_fun, *args, **kwargs) -> Dict: 1503 | result = {} 1504 | 1505 | gazetaURL = f"https://konto.gazeta.pl/konto/checkLogin?login={target}&nosuggestions=true" 1506 | headers = { 1507 | "User-Agent": random.choice(uaLst), 1508 | "Referer": "https://konto.gazeta.pl/konto/rejestracja.do", 1509 | "Accept": "*/*" 1510 | } 1511 | 1512 | sreq = req_session_fun() 1513 | 1514 | try: 1515 | gazetaChk = await sreq.get(gazetaURL, headers=headers, timeout=kwargs.get('timeout', 5)) 1516 | 1517 | body = await gazetaChk.json(content_type=None) 1518 | 1519 | if body["available"] == "0": 1520 | result["Gazeta.pl"] = f"{target}@gazeta.pl" 1521 | 1522 | except Exception as e: 1523 | logger.error(e, exc_info=True) 1524 | 1525 | await sreq.close() 1526 | 1527 | return result 1528 | 1529 | async def intpl(target, req_session_fun, *args, **kwargs) -> Dict: 1530 | result = {} 1531 | 1532 | intURL = "https://int.pl/v1/user/checkEmail" 1533 | headers = { 1534 | "User-Agent": random.choice(uaLst), 1535 | "Origin": "https://int.pl", 1536 | "Referer": "https://int.pl/", 1537 | "Accept": "application/json, text/plain, */*", 1538 | "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8" 1539 | } 1540 | 1541 | data = f"login={target}&subdomain=&domain=int.pl" 1542 | 1543 | sreq = req_session_fun() 1544 | 1545 | try: 1546 | intChk = await sreq.post(intURL, headers=headers, data=data, timeout=kwargs.get('timeout', 5)) 1547 | 1548 | body = await intChk.json(content_type=None) 1549 | 1550 | if body["result"]["data"]["login"] == 0: 1551 | result["int.pl"] = f"{target}@int.pl" 1552 | 1553 | except Exception as e: 1554 | logger.error(e, exc_info=True) 1555 | 1556 | await sreq.close() 1557 | 1558 | return result 1559 | 1560 | async def o2(target, req_session_fun, *args, **kwargs) -> Dict: 1561 | result = {} 1562 | 1563 | o2URL = "https://poczta.o2.pl/api/v1/public/registration/accounts/availability" 1564 | headers = { 1565 | "User-Agent": random.choice(uaLst), 1566 | "Content-Type": "application/json;charset=UTF-8", 1567 | "Origin": "https://poczta.o2.pl", 1568 | "Referer": "https://poczta.o2.pl/rejestracja/", 1569 | "Accept": "application/json" 1570 | } 1571 | 1572 | data = f'{{"login":"{target}","sex":""}}' 1573 | 1574 | sreq = req_session_fun() 1575 | 1576 | try: 1577 | wpChk = await sreq.put(o2URL, headers=headers, data=data, timeout=kwargs.get('timeout', 5)) 1578 | 1579 | body = await wpChk.json(content_type=None) 1580 | 1581 | if "Podany login jest niedostępny." in str(body): 1582 | result["O2"] = f"{target}@o2.pl" 1583 | 1584 | except Exception as e: 1585 | logger.error(e, exc_info=True) 1586 | 1587 | await sreq.close() 1588 | 1589 | return result 1590 | 1591 | async def interia(target, req_session_fun, *args, **kwargs) -> Dict: 1592 | result = {} 1593 | interiaSucc = [] 1594 | 1595 | interiaLst = ["interia.pl", 1596 | "interia.eu", 1597 | "intmail.pl", 1598 | "adresik.net", 1599 | "vip.interia.pl", 1600 | "ogarnij.se", 1601 | "poczta.fm", 1602 | "interia.com", 1603 | "interiowy.pl", 1604 | "pisz.to", 1605 | "pacz.to"] 1606 | 1607 | 1608 | headers = { 1609 | 'User-Agent': random.choice(uaLst), 1610 | 'Content-Type': 'application/json', 1611 | 'Accept': 'application/json; q=1.0, text/*; q=0.8, */*; q=0.1', 1612 | 'Origin': 'https://konto-pocztowe.interia.pl', 1613 | 'Referer': 'https://konto-pocztowe.interia.pl/' 1614 | } 1615 | 1616 | sreq = req_session_fun() 1617 | 1618 | for maildomain in interiaLst: 1619 | try: 1620 | targetMail = f"{target}@{maildomain}" 1621 | data = f'{{"email":"{targetMail}"}}' 1622 | 1623 | interiaUrl = "https://konto-pocztowe.interia.pl/odzyskiwanie-dostepu/sms" 1624 | chkInteria = await sreq.post(interiaUrl, headers=headers, data=data, timeout=kwargs.get('timeout', 5)) 1625 | 1626 | async with chkInteria: 1627 | if chkInteria.status == 404: 1628 | resp = await chkInteria.json(content_type=None) 1629 | if resp["data"]["message"] == "Użytkownik nie istnieje w systemie": 1630 | interiaSucc.append(targetMail) 1631 | except Exception as e: 1632 | logger.error(e, exc_info=True) 1633 | 1634 | await asyncio.sleep(random.uniform(2, 4)) 1635 | 1636 | if interiaSucc: 1637 | result["Interia"] = interiaSucc 1638 | 1639 | await sreq.close() 1640 | 1641 | return result 1642 | 1643 | async def tpl(target, req_session_fun, *args, **kwargs) -> Dict: 1644 | result = {} 1645 | tplSucc = [] 1646 | 1647 | tplLst = ["t.pl", 1648 | "malio.pl", 1649 | "wg.pl", 1650 | "2.pl", 1651 | "jo.pl", 1652 | "pocz.pl", 1653 | "t7.pl", 1654 | "0.pl", 1655 | "uk.pl"] 1656 | 1657 | 1658 | headers = {'User-Agent': random.choice(uaLst)} 1659 | sreq = req_session_fun() 1660 | try: 1661 | tplUrl = f"https://t.pl/reg.php?nazwa={target}" 1662 | 1663 | chkTpl = await sreq.get(tplUrl, headers=headers, timeout=kwargs.get('timeout', 5)) 1664 | 1665 | async with chkTpl: 1666 | if chkTpl.status == 200: 1667 | resp = await chkTpl.text() 1668 | for maildomain in tplLst: 1669 | targetMail = f"{target}@{maildomain}" 1670 | if f"{targetMail}" in resp: 1671 | tplSucc.append(targetMail) 1672 | except Exception as e: 1673 | logger.error(e, exc_info=True) 1674 | 1675 | if tplSucc: 1676 | result["T.pl"] = tplSucc 1677 | 1678 | await sreq.close() 1679 | 1680 | return result 1681 | 1682 | async def onet(target, req_session_fun, *args, **kwargs) -> Dict: 1683 | result = {} 1684 | onetSucc = [] 1685 | 1686 | onetLst = ["onet.pl", 1687 | "op.pl", 1688 | "adres.pl", 1689 | "vp.pl", 1690 | "onet.eu", 1691 | "cyberia.pl", 1692 | "pseudonim.pl", 1693 | "autograf.pl", 1694 | "opoczta.pl", 1695 | "spoko.pl", 1696 | "amorki.pl", 1697 | "buziaczek.pl", 1698 | "poczta.onet.pl", 1699 | "poczta.onet.eu", 1700 | "onet.com.pl", 1701 | "vip.onet.pl"] 1702 | 1703 | 1704 | headers = { 1705 | "User-Agent": random.choice(uaLst), 1706 | "Content-Type": "application/json", 1707 | "Accept": "application/json", 1708 | "Referer": "https://konto.onet.pl/" 1709 | } 1710 | 1711 | data = { 1712 | "login": target, 1713 | "captcha_response":"meow", 1714 | "state":"https://poczta.onet.pl/" 1715 | } 1716 | 1717 | onetUrl = "https://konto.onet.pl/newapi/oauth/check-register-email-identity" 1718 | 1719 | sreq = req_session_fun() 1720 | try: 1721 | chkOnet = await sreq.post(onetUrl, headers=headers, data=json.dumps(data), timeout=kwargs.get('timeout', 5)) 1722 | 1723 | async with chkOnet: 1724 | if chkOnet.status == 200: 1725 | body = await chkOnet.json(content_type=None) 1726 | 1727 | for maildomain in onetLst: 1728 | targetMail = f"{target}@{maildomain}" 1729 | if not targetMail in body["emails"]: 1730 | onetSucc.append(targetMail) 1731 | 1732 | except Exception as e: 1733 | logger.error(e, exc_info=True) 1734 | 1735 | if onetSucc: 1736 | result["Onet"] = onetSucc 1737 | 1738 | await sreq.close() 1739 | 1740 | return result 1741 | 1742 | #################################################################################### 1743 | def show_banner(): 1744 | banner = r""" 1745 | 1746 | ,-. ^ 1747 | ( ( _,---._ __ / \ 1748 | ) ) .-' `./ / \ 1749 | ( ( ,' `/ /: 1750 | \ `-" \'\ / | 1751 | . , \ \ / | 1752 | / @ ,'-`----Y | 1753 | ( ; : : 1754 | | .-. _,-' | / 1755 | | | ( ( | / 1756 | ) ( \ `.___________:/ 1757 | `..' `--' :mailcat: 1758 | """ 1759 | for color, part in zip(range(75, 89), banner.split('\n')[1:]): 1760 | print(f"\033[1;38;5;{color}m{part}\033[0m") 1761 | sleep(0.1337) 1762 | 1763 | 1764 | async def print_results(checker, target, req_session_fun, is_verbose_mode, timeout): 1765 | checker_name = checker.__name__ 1766 | if is_verbose_mode: 1767 | print(f'Running {checker_name} checker for {target}...') 1768 | 1769 | err = None 1770 | res = await checker(target, req_session_fun, timeout) 1771 | 1772 | if isinstance(res, tuple): 1773 | res, err = res 1774 | 1775 | if not res: 1776 | if is_verbose_mode: 1777 | print(f'No results for {checker_name}') 1778 | res = {} 1779 | 1780 | if err: 1781 | print(f'Error while checking {checker_name}: {err}') 1782 | return {checker_name: err} 1783 | 1784 | for provider, emails in res.items(): 1785 | print(f'\033[1;38;5;75m{provider}: \033[0m') 1786 | if isinstance(emails, str): 1787 | emails = [emails] 1788 | for email in emails: 1789 | print(f'* {email}') 1790 | 1791 | return {checker_name: res} if res else {checker_name: None} 1792 | 1793 | 1794 | CHECKERS = [gmail, yandex, proton, mailRu, 1795 | rambler, tuta, yahoo, outlook, 1796 | zoho, eclipso, posteo, mailbox, 1797 | firemail, fastmail, startmail, 1798 | xmail, ukrnet, #bigmir, 1799 | runbox, iCloud, duckgo, hushmail, 1800 | ctemplar, aikq, emailn, vivaldi, 1801 | mailDe, wp, gazeta, intpl, 1802 | o2, interia, tpl, onet] # -kolab -lycos(false((( ) 1803 | 1804 | async def start(): 1805 | parser = argparse.ArgumentParser( 1806 | formatter_class=argparse.RawDescriptionHelpFormatter, 1807 | description="Mailcat", 1808 | ) 1809 | parser.add_argument( 1810 | '-p', 1811 | '--provider', 1812 | action="append", 1813 | metavar='', 1814 | dest="providers", 1815 | default=[], 1816 | help="Specify one or more (-p for each) mail providers by name: " + 1817 | ', '.join(map(lambda f: f.__name__, CHECKERS)), 1818 | ) 1819 | parser.add_argument( 1820 | "username", 1821 | nargs='*', 1822 | metavar="USERNAME", 1823 | help="One username to search emails by", 1824 | ) 1825 | parser.add_argument( 1826 | '-l', 1827 | '--list', 1828 | action="store_true", 1829 | default=False, 1830 | help="List all the supported providers", 1831 | ) 1832 | parser.add_argument( 1833 | '-s', 1834 | '--silent', 1835 | action="store_true", 1836 | default=False, 1837 | help="Hide wonderful mailcat intro animation", 1838 | ) 1839 | parser.add_argument( 1840 | '-v', 1841 | '--verbose', 1842 | action="store_true", 1843 | default=False, 1844 | help="Verbose output about search progress.", 1845 | ) 1846 | parser.add_argument( 1847 | '-d', 1848 | '--debug', 1849 | action="store_true", 1850 | default=False, 1851 | help="Display checking errors.", 1852 | ) 1853 | parser.add_argument( 1854 | '--tor', 1855 | action="store_true", 1856 | default=False, 1857 | help="Use Tor where you need it", 1858 | ) 1859 | parser.add_argument( 1860 | '--proxy', 1861 | type=str, 1862 | default="", 1863 | help="Proxy string (e.g. https://user:pass@1.2.3.4:8080)", 1864 | ) 1865 | parser.add_argument( 1866 | '-t', 1867 | '--timeout', 1868 | type=int, 1869 | default=10, 1870 | help="Timeout for every check, 10 seconds by default", 1871 | ) 1872 | parser.add_argument( 1873 | '-m', 1874 | '--max-connections', 1875 | type=int, 1876 | default=10, 1877 | help="Max connections to check (number of simultaneously checked providers), 10 by default", 1878 | ) 1879 | parser.add_argument( 1880 | '--progressbar', 1881 | action="store_true", 1882 | default=False, 1883 | help="Show progressbar", 1884 | ) 1885 | args = parser.parse_args() 1886 | 1887 | if args.debug: 1888 | logger.setLevel(logging.WARNING) 1889 | 1890 | if not args.silent: 1891 | show_banner() 1892 | 1893 | if args.list: 1894 | print('Supported email providers: ') 1895 | print(' ' + ', '.join(map(lambda f: f.__name__, CHECKERS))) 1896 | 1897 | target = args.username 1898 | 1899 | if len(target) != 1: 1900 | print('Please, specify one username to search!') 1901 | sys.exit(1) 1902 | else: 1903 | target = target[0] 1904 | 1905 | if "@" in target: 1906 | target = target.split('@')[0] 1907 | 1908 | if args.providers: 1909 | pset = set(map(lambda s: s.lower(), args.providers)) 1910 | checkers = [c for c in CHECKERS if c.__name__.lower() in pset] 1911 | if not checkers: 1912 | print(f'Can not find providers {", ".join(args.providers)}') 1913 | else: 1914 | checkers = CHECKERS 1915 | 1916 | if args.proxy: 1917 | req_session_fun = via_proxy(args.proxy) 1918 | print(f'Using proxy {args.proxy} to make requests...') 1919 | elif args.tor: 1920 | req_session_fun = via_tor 1921 | print('Using tor to make requests...') 1922 | else: 1923 | req_session_fun = simple_session 1924 | 1925 | tasks = [( 1926 | print_results, 1927 | [checker, target, req_session_fun, args.verbose, args.timeout], 1928 | {}, 1929 | ) for checker in checkers] 1930 | 1931 | executor = AsyncioProgressbarQueueExecutor( 1932 | logger=logger, 1933 | in_parallel=args.max_connections, 1934 | timeout=args.timeout + 0.5, 1935 | progress_func=tqdm.tqdm if args.progressbar else stub_progress, 1936 | ) 1937 | 1938 | await executor.run(tasks) 1939 | 1940 | if __name__ == '__main__': 1941 | try: 1942 | asyncio.run(start()) 1943 | except KeyboardInterrupt: 1944 | sys.exit(0) 1945 | 1946 | 1947 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiohappyeyeballs==2.4.4 2 | aiohttp==3.11.10 3 | aiohttp_socks==0.9.1 4 | aiosignal==1.3.1 5 | aiosmtplib==3.0.2 6 | appdirs==1.4.4 7 | attrs==24.2.0 8 | beautifulsoup4==4.12.3 9 | bs4==0.0.2 10 | certifi==2024.8.30 11 | charset-normalizer==3.4.0 12 | cssselect==1.2.0 13 | dnspython==2.7.0 14 | fake-useragent==2.0.1 15 | frozenlist==1.5.0 16 | idna==3.10 17 | importlib_metadata==8.5.0 18 | importlib_resources==6.4.5 19 | lxml==5.3.0 20 | lxml_html_clean==0.4.1 21 | multidict==6.1.0 22 | parse==1.20.2 23 | propcache==0.2.1 24 | pyee==11.1.1 25 | pyppeteer==2.0.0 26 | pyquery==2.0.1 27 | python-socks==2.5.3 28 | requests==2.32.3 29 | requests-html==0.10.0 30 | soupsieve==2.6 31 | tqdm==4.67.1 32 | typing_extensions==4.12.2 33 | urllib3==1.26.20 34 | w3lib==2.2.1 35 | websockets==10.4 36 | yarl==1.18.3 37 | zipp==3.21.0 38 | --------------------------------------------------------------------------------