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

Improve IMAP logic and fixed bugs #46

Open
CryptoBarge opened this issue Jan 16, 2025 · 0 comments
Open

Improve IMAP logic and fixed bugs #46

CryptoBarge opened this issue Jan 16, 2025 · 0 comments

Comments

@CryptoBarge
Copy link

class LinkExtractor:
_link_cache = LinkCache()

def __init__(self, imap_server: str, email: str, password: str, max_attempts: int = 8, delay_seconds: int = 5, redirect_email: Optional[str] = None):
    self.imap_server = imap_server
    self.email = email
    self.password = password
    self.max_attempts = max_attempts
    self.delay_seconds = delay_seconds
    self.redirect_email = redirect_email
    self.link_patterns = [
        r"https://u\d+\.ct\.sendgrid\.net/ls/click\?upn=[A-Za-z0-9\-_%.]+(?:[A-Za-z0-9\-_%.=&])*",
        r"(https://www\.aeropres\.in/chromeapi/dawn/v1/userverify/verifyconfirm\?key=[a-f0-9-]+)",
        r"(https?://webmail\.online/go\.php\?r=(?:[A-Za-z0-9+/]|%[0-9A-Fa-f]{2})+)"
    ]

async def extract_link(self, proxy: Optional[Proxy] = None) -> OperationResult:
    logger.info(f"Account: {self.email} | Checking email for link...")
    return await self.search_with_retries(proxy)

def _collect_messages(self, mailbox: MailBox):
    messages = []

    for msg in mailbox.fetch(reverse=True, criteria=AND(all="[email protected]"), limit=10, mark_seen=True):
        if msg.from_ and (msg.from_.startswith("[email protected]") or msg.from_.startswith("hello_at_dawn_internet_com")):
            msg_date = msg.date.replace(tzinfo=timezone.utc) if msg.date.tzinfo is None else msg.date
            messages.append((msg, msg_date))

    return messages

def _process_latest_message(self, messages):
    if not messages:
        return None

    latest_msg, latest_date = max(messages, key=lambda x: x[1])
    body = latest_msg.text or latest_msg.html
    if not body:
        return None

    for link_pattern in self.link_patterns:
        if match := re.search(link_pattern, body):
            code = match.group(0)
            if self._link_cache.is_link_used(code):
                return None
            self._link_cache.add_link(self.email, code)
            return code
    return None

async def _search_in_all_folders(self, proxy: Optional[Proxy]) -> Optional[str]:
    def search_in():
        all_messages = []
        with MailBoxClient(host=self.imap_server, proxy=proxy, timeout=30).login(self.email, self.password) as mailbox:
            for folder in mailbox.folder.list():
                mailbox.folder.set(folder.name)
                messages = self._collect_messages(mailbox)
                all_messages.extend(messages)
        return self._process_latest_message(all_messages)

    return await asyncio.to_thread(search_in)

async def search_with_retries(self, proxy: Optional[Proxy] = None) -> OperationResult:
    for attempt in range(self.max_attempts):
        link = await self._search_in_all_folders(proxy)
        if link:
            return {"status": True, "identifier": self.email, "data": link}

        if attempt < self.max_attempts - 1:
            await asyncio.sleep(self.delay_seconds)

    return {"status": False, "identifier": self.email, "data": "Max attempts reached"}
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