import smtplib
import ssl
import imaplib
import email
import threading
import time
import random
from concurrent.futures import ThreadPoolExecutor, as_completed
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from queue import Queue
from colorama import init, Fore
import socks
import socket

init(autoreset=True)
print(Fore.CYAN + "Ai by Revo - SMTP Checker (Fast Mode)")

# ------------------------- Ustawienia agresywne -------------------------
MAX_WORKERS = 50           # więcej wątków
SEMAPHORE_LIMIT = 30       # max jednoczesnych połączeń SMTP
CONNECT_TIMEOUT = 8       # krótszy timeout połączenia
SMTP_OP_TIMEOUT = 12       # krótszy timeout operacji SMTP
RETRY_COUNT = 1
BACKOFF_BASE = 1           # mniejszy backoff, szybciej próbujemy
IMAP_POLL_INTERVAL = 3
# ------------------------------------------------------------------------

semaphore = threading.Semaphore(SEMAPHORE_LIMIT)
lock = threading.Lock()
success_queue = Queue()

# --------------------- Funkcje pomocnicze ---------------------
def load_smtp_servers(filename):
    with open(filename, 'r') as f:
        return [line.strip().split('|') for line in f if line.strip() and len(line.strip().split('|')) == 4]

def load_proxies(filename):
    with open(filename, 'r') as f:
        return [line.strip() for line in f if line.strip()]

def set_proxy(proxy_type, proxy_str):
    ip, port = proxy_str.split(':')
    port = int(port)
    types = {'http': socks.HTTP, 'https': socks.HTTP, 'socks4': socks.SOCKS4, 'socks5': socks.SOCKS5}
    socks.setdefaultproxy(types[proxy_type], ip, port)
    socket.socket = socks.socksocket

def reset_socket():
    socket.socket = socket._socketobject

def send_email(smtp_info, to_email, subject, content, use_proxy, proxy_type, proxy_list):
    host, port, user, password = smtp_info
    port = int(port)
    message = MIMEMultipart()
    message['From'] = user
    message['To'] = to_email
    message['Subject'] = subject
    message.attach(MIMEText(content, 'plain'))

    for attempt in range(RETRY_COUNT + 1):
        if use_proxy and proxy_list:
            proxy = random.choice(proxy_list)
            set_proxy(proxy_type, proxy)

        try:
            with semaphore:
                context = ssl.create_default_context()
                if port == 465:
                    server = smtplib.SMTP_SSL(host, port, timeout=CONNECT_TIMEOUT, context=context)
                else:
                    server = smtplib.SMTP(host, port, timeout=CONNECT_TIMEOUT)
                    server.starttls(context=context)
                server.login(user, password)
                server.sendmail(user, to_email, message.as_string())
                server.quit()
                print(Fore.GREEN + f"[+] Success: {host}|{port}|{user}|{password}")
                success_queue.put(user)
                return
        except Exception as e:
            backoff = BACKOFF_BASE * (attempt + 1)
            print(Fore.YELLOW + f"[WARN] Attempt {attempt+1} failed for {user}@{host}:{port} -> {str(e)}. Backing off {backoff}s")
            time.sleep(backoff)
        finally:
            if use_proxy:
                reset_socket()
    print(Fore.RED + f"[-] Failed all attempts: {host}|{port}|{user}|{password}")

def imap_check(server, user, password, subject, duration_minutes):
    found_senders = set()
    try:
        mail = imaplib.IMAP4_SSL(server)
        mail.login(user, password)
        print(Fore.GREEN + "[+] Logged into recipient mailbox.")
        mail.select("inbox")
        duration_seconds = duration_minutes * 60
        for elapsed in range(duration_seconds):
            if elapsed % IMAP_POLL_INTERVAL == 0 or elapsed == 0:
                result, data = mail.search(None, f'(SUBJECT "{subject}")')
                if result == 'OK':
                    ids = data[0].split()
                    for msg_id in ids:
                        result, msg_data = mail.fetch(msg_id, '(RFC822)')
                        if result == 'OK':
                            msg = email.message_from_bytes(msg_data[0][1])
                            from_addr = msg['From']
                            if from_addr not in found_senders:
                                print(Fore.YELLOW + f"[+] Found email from: {from_addr}")
                                found_senders.add(from_addr)
                                success_queue.put(from_addr)
            time.sleep(1)
        mail.logout()
        print(Fore.GREEN + "[+] IMAP check finished.")
    except Exception as e:
        print(Fore.RED + f"[-] IMAP login/check failed: {e}")

# ------------------------- MAIN -------------------------
def main():
    smtp_file = input("Enter SMTP servers filename: ")
    threads = int(input("Enter number of threads (max 50): "))
    to_email = input("Enter recipient email: ")
    subject = input("Enter email subject: ")
    content = input("Enter email content: ")
    use_proxy = input("Use proxy? (y/n): ").lower() == 'y'

    proxy_list = []
    proxy_type = ''
    if use_proxy:
        proxy_file = input("Enter proxy list filename: ")
        proxy_type = input("Type of proxy (http/socks4/socks5): ").lower()
        proxy_list = load_proxies(proxy_file)

    smtp_servers = load_smtp_servers(smtp_file)

    with ThreadPoolExecutor(max_workers=threads) as executor:
        futures = [executor.submit(send_email, smtp, to_email, subject, content, use_proxy, proxy_type, proxy_list)
                   for smtp in smtp_servers]
        for future in as_completed(futures):
            pass

    print(Fore.CYAN + "[i] SMTP check finished. Now IMAP verification.")
    imap_server = input("Enter recipient IMAP server: ")
    imap_user = input("Enter recipient IMAP user: ")
    imap_pass = input("Enter recipient IMAP password: ")
    duration = int(input("How many minutes to check inbox for replies? "))
    imap_check(imap_server, imap_user, imap_pass, subject, duration)

    # Zapis działających SMTP
    good_file = 'good.txt'
    good_set = set()
    while not success_queue.empty():
        sender = success_queue.get()
        good_set.add(sender)

    with open(good_file, 'w') as f:
        for smtp_user in good_set:
            for s in smtp_servers:
                if s[2] == smtp_user:
                    f.write('|'.join(s) + '\n')

    print(Fore.GREEN + f"[+] Saved {len(good_set)} working SMTP servers to good.txt")
    print(Fore.CYAN + "Ai by Revo - Done.")

if __name__ == '__main__':
    main()
