Skip to content

feat: add email module for Alza - #492

Open
beranka wants to merge 1 commit into
kaifcodec:mainfrom
beranka:feat/add-alza-email-module
Open

feat: add email module for Alza#492
beranka wants to merge 1 commit into
kaifcodec:mainfrom
beranka:feat/add-alza-email-module

Conversation

@beranka

@beranka beranka commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Adds an email scan module for Alza.

Alza has multiple websites for different countries in Central Europe; this checks all of them in a loop.

How it works

For each website:

  • Retrieves cookies when requesting the main page.
  • Uses an API endpoint which returns:
    • LoginAvailabilityType field, set to:
      • 1 (account associated with the email),
      • 2 (email used for an order without an account),
      • 0 (email not found),
      • there might be other values, but those did not appear when testing different emails.
    • Other fields are also returned, but I did not notice any value changes during testing.

Then returns a Result with status:

  • available if all websites returned LoginAvailabilityType: 0.
  • taken if at least one website returned LoginAvailabilityType: 1 or LoginAvailabilityType: 2; also returns two comma-separated lists:
    • websites where the email is associated with an account,
    • websites where the email was used for an order without an account.
  • error if an error occurred while checking any of the websites.

Testing

Manually tested (and got expected results) with:

  • Email belonging to only one account on one website (for each website)
  • Email registered nowhere and not used for any orders
  • Email belonging to an account on each website
  • Email used previously for an order without an account on one of the websites

It's a little bit more complex than I expected (sorry), but I think it makes sense to check each of the regional websites 🙂

@kristoisberg

Copy link
Copy Markdown
Collaborator

@kaifcodec Thoughts on this? When I added the two regional versions of Yaga, I created separate modules for each. Here, with five sites, this would get a bit spammy...

return Result.taken(url=main_url, extra={"has_account": True})
case 2:
# Orders with this email were created, but the email does not belong to any account
return Result.taken(url=main_url, extra={"has_account": False})

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This case will definitely become confusing for users without reading source code - the module will report the email as "registered", but simultaneously says an account does not exist. I'm not even sure how to express these results better... I definitely wouldn't exclude this case, since even "has made an order" is useful information.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@beranka

  1. You don't need to pass the extra dictionary for case 1. Returning Result.taken(...) already conveys that has_account=True, so including it in extra is redundant.

  2. For case 2, you can use the reason parameter instead. All three result types (.taken(), .error(), and .available()) support it, so you can do something like:

return Result.taken(
    url=main_url,
    reason="This email is not registered, but it has been used to place an order.",
    extra={"has_account": False},
)

@kristoisberg
I think this better represents the OSINT value of the result. Even if the email isn't registered, it has still interacted with the site, so returning Result.taken(...) is reasonable. The reason explains why it's considered a hit, while extra provides the additional context that the email doesn't actually have an account.

@kaifcodec

Copy link
Copy Markdown
Owner

@kaifcodec Thoughts on this? When I added the two regional versions of Yaga, I created separate modules for each. Here, with five sites, this would get a bit spammy...

@kristoisberg Good catch. They most likely use separate databases for each regional site rather than treating all five domains as a single service.

So @beranka, I think it's better to open another PR where you split these into five separate modules. It will be more scalable and also more user-friendly, since users can immediately identify the region from the results instead of only getting to know that the email is registered on "Alza".

The filenames could be something like:

  • alza_cz.py
  • alza_hu.py
  • alza_sk.py
  • alza_at.py
  • alza_de.py

Our helper functions already convert _ to . when importing modules, and . back to _ when parsing args.module, so you don't need to worry about that part. Just use underscores in the filenames.

@kaifcodec

Copy link
Copy Markdown
Owner

@beranka Would you like to take more time working on this PR, or should I label it as help wanted so other contributors can take this and work on it?

@beranka

beranka commented Aug 5, 2026

Copy link
Copy Markdown
Contributor Author

@beranka Would you like to take more time working on this PR, or should I label it as help wanted so other contributors can take this and work on it?

I am just busy with work this week, but I will take a look at it on Sunday.

@kaifcodec

Copy link
Copy Markdown
Owner

That's great. Thank you for the clarification.

@beranka

beranka commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

So @beranka, I think it's better to open another PR where you split these into five separate modules. It will be more scalable and also more user-friendly, since users can immediately identify the region from the results instead of only getting to know that the email is registered on "Alza".

@kaifcodec Why another PR?

Also what should I do to avoid repeating the same code for each variant? Could I maybe create alza_common.py somewhere? Or keep the _check_given_website() in one of the variants and import it to others? I don't like the idea of having 5 almost identical files...

@kaifcodec

Copy link
Copy Markdown
Owner
  1. PR Workflow: You can keep using this current PR and push the refactored commit here but a new PR is recommended for keeping the commit history clean.

  2. Don't worry about minor header/URL string overlap across the 5 files. We explicitly prefer having 5 straightforward, independent module files (alza_cz.py, alza_sk.py, etc.) over creating complex helper abstractions or cross-importing between modules.

    Keeping each module self-contained makes it super easy to maintain, if Alza changes their .hu backend or cookie requirements tomorrow, anyone can update alza_hu.py directly without digging through shared helper abstractions or risking breaking .cz, also you can't create some helper like _common.py as it goes against contributing guidelines and standard user-scanner module import patterns.

@brunolm brunolm added the email module addition PRs or issues related to new email_scan module additions label Aug 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

email module addition PRs or issues related to new email_scan module additions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants