Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem... #68

Open
obnoxiousish opened this issue Feb 8, 2024 · 1 comment
Open

Problem... #68

obnoxiousish opened this issue Feb 8, 2024 · 1 comment

Comments

@obnoxiousish
Copy link

Hi, I created a few test scripts:

  1. Using imaplib python & multiprocessing + multi threading
  2. Using aioimaplib python & asyncio
  3. Using smtpproto python & trio

My imaplib script, connects & sends mail from about 80-90SMTP servers I give it
My aioimaplib script, connects & send mail from about 100-110
SMTP servers I give it
My smtpproto script, connects & send mail from about 20~ of the SMTP servers I give it

These tests were done using identical input smtps. Not sure what the problem is, as smtpproto is supposed to support plaintext auth, over SSL and STARTTLS & plaintext.

I can potentially provide list to devs for trying to solve this issue. My guess would be that it's not handling starttls properly..? I dont know.

@obnoxiousish
Copy link
Author

obnoxiousish commented Feb 8, 2024

import trio
from smtpproto.client import AsyncSMTPClient
from smtpproto.auth import LoginAuthenticator, PlainAuthenticator, SMTPAuthenticator
from utils.general import create_permissive_ssl_context
from email.message import EmailMessage
import logging

async def smtpProtoTest(line):
    splitLine = line.split(",")
    
    smtpServer = splitLine[0].strip()
    try:
        smtpPort = int(splitLine[1])
    except ValueError:
        logging.error(f"Invalid port for {smtpServer}")
        return {'success': False, 'stage': 'zero', 'error': 'Invalid port'}
    smtpUsername = splitLine[2]
    smtpPassword = splitLine[3]
    smtpStatus = splitLine[4].strip()
    
    client = None  # Initialize client variable outside try-except to ensure visibility
    try:
        async with AsyncSMTPClient(
            host=smtpServer,
            port=smtpPort,
            timeout=7,
            domain=smtpServer,
            authenticator=PlainAuthenticator(smtpUsername, smtpPassword),
            #ssl_context=create_permissive_ssl_context(),
        ) as mailer:

            msg = EmailMessage()
            msg['From'] = smtpUsername
            msg['To'] = ''
            msg['Subject'] = 'Test'
            msg.set_content('Test')
    
            await mailer.send_message(msg)
            
            print(f"Logged in with plain without SSL context = None {smtpServer}")
            
            return {'success': True, 'stage': 'one'}
    except Exception as e:
        #logging.error(f'Error during normal connect for {smtpServer}: {e}')
        try:
            async with AsyncSMTPClient(
                host=smtpServer,
                port=smtpPort,
                timeout=7,
                domain=smtpServer,
                authenticator=PlainAuthenticator(smtpUsername, smtpPassword),
                ssl_context=create_permissive_ssl_context(),
            ) as mailer:
                msg = EmailMessage()
                msg['From'] = smtpUsername
                msg['To'] = 'tinderagainlol@proton.me'
                msg['Subject'] = 'Test'
                msg.set_content('Test')
        
                await mailer.send_message(msg)
                
                print(f"Logged in with plain authenticator with SSL for {smtpServer}")
                
                return {'success': True, 'stage': 'two'}
        except Exception as e:
            #logging.error(f'Error during SSL connect for {smtpServer}: {e}')
            return {'success': False, 'stage': 'two', 'error': str(e)}

async def logReturns(results, *args):
    returnData = await smtpProtoTest(*args)
    
    results.append(returnData)

async def main():
    results = []
    smtpCsv = open("smtps.csv", "r").read().splitlines()
    
    async with trio.open_nursery() as nursery:
        for line in smtpCsv:
            nursery.start_soon(logReturns, results, line)

    # Ensure this print statement occurs after all tasks have been awaited
    await trio.sleep(0.2)  # Small delay to ensure all logging messages are flushed
    
    success = 0
    failed = 0
    
    for res in results:
        if res.get('success'):
            success += 1
        else:
            failed += 1
            
    print(success, failed)
    
trio.run(main)

aiosmtplib script:

import asyncio
import aiosmtplib
import numpy

from email.message import EmailMessage
from utils.dnsh import DNSHelper
from python_socks.async_.asyncio import Proxy
from utils.general import create_permissive_ssl_context


class Counter:
    def __init__(self):
        self.count = 0

    def increment(self):
        self.count += 1


mainCounter = Counter()



async def smtpAIOTest(line):
    def prepareEmail(smtpUsername):
        email = EmailMessage()
        email.set_content("This is a test email")
        email["From"] = smtpUsername
        email["To"] = "13gmass37@gmail.com"
        email["Subject"] = "Test email"
    
        return email
    
    splitLine = line.split(",")

    smtpServer = splitLine[0].strip().rstrip()
    smtpPort = splitLine[1]
    smtpUsername = splitLine[2]
    smtpPassword = splitLine[3]
    smtpStatus = splitLine[4].rstrip().strip()
    
    if '.' not in smtpServer:
        return {"success": False, "message": "Invalid config no . in server"}
    
    if smtpPort.isnumeric():
        smtpPort = int(smtpPort)

    proxyStr = numpy.random.choice(
        [
            'socks5://127.0.0.1:43594',
            'socks5://127.0.0.1:31337'
        ]
    )
    

    try:
        dnsHelp = DNSHelper(proxy=proxyStr)
        serverIP = await dnsHelp.resolveUsingDoH(smtpServer)
        
        if not serverIP:
            serverIP = smtpServer
        else:
            serverIP=serverIP[0]
        
        if not serverIP:
            serverIP = smtpServer
        
        proxyObj = Proxy.from_url(proxyStr)
        
        proxySock = await proxyObj.connect(serverIP, smtpPort)
        
        client = aiosmtplib.SMTP(
            sock=proxySock,
            hostname=None,
            port=None,
            socket_path=None,
            timeout=15,
            start_tls=False,
            tls_context=create_permissive_ssl_context(),
            use_tls=False,
        )

        await client.connect()
        
        try:
            await client.starttls()
        except Exception as e:
            pass
        
        await client.login(smtpUsername, smtpPassword)
        
        msgResults, msgData = await client.send_message(prepareEmail(smtpUsername))

        if 'OK' not in str(msgData):
            return {"success": False, "message": f'stage 1: {str(msgData)}'}

        if 'OK' in str(msgData):
            mainCounter.increment()
        
        if 'OK' in str(msgData):
            print(f"Success: STAGE1 {smtpServer} using {proxyStr} and {serverIP} and {smtpPort} and {smtpUsername} and {smtpPassword} and {smtpStatus}")
        
        return {"success": True, "stage": '1'}
    except Exception as e:
        print(f"Error: {e} | During Normal connect")

        try:
            proxyStr = numpy.random.choice(
                [
                    'socks5://127.0.0.1:43594',
                    'socks5://127.0.0.1:31337'
                ]
            )
            
            dnsHelp = DNSHelper(proxy=proxyStr)
            serverIP = await dnsHelp.resolveUsingDoH(smtpServer)
            
            
            proxyObj = Proxy.from_url(proxyStr)
            proxySock = await proxyObj.connect(smtpServer, smtpPort)
            
            sslClient = aiosmtplib.SMTP(
                sock=proxySock,
                hostname=None,
                port=None,
                socket_path=None,
                timeout=15,
                tls_context=create_permissive_ssl_context(),
                use_tls=True,
            )
            connectResults = await sslClient.connect()
            loginResults = await sslClient.login(smtpUsername, smtpPassword)

            mainCounter.increment()
            
            print(f"Success: STAGE2 {smtpServer} using {proxyStr} and {serverIP} and {smtpPort} and {smtpUsername} and {smtpPassword} and {smtpStatus}")
            
            return {"success": True, "stage": '2'}
        except Exception as e:
            print(f"Error: {e} | During SSL connect")
            return {"success": False, "message": str(e)}


async def main():
    tasks = []
    smtpCsv = open("smtps.csv", "r").read().splitlines()

    for line in smtpCsv:
        tasks.append(smtpAIOTest(line))

    results = await asyncio.gather(*tasks)

    print(f"Processed {mainCounter.count} emails.")
    
    successCount = 0
    
    for result in results:
        if result.get('success'):
            print(f"Success: {result}")
            successCount += 1
            
    print(f"Success count: {successCount}")


if __name__ == "__main__":
    asyncio.run(main())

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant