├── .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 |
--------------------------------------------------------------------------------
|