Skip to content

Commit

Permalink
Add support for authenticated proxies in chrome and undetected-chrome
Browse files Browse the repository at this point in the history
  • Loading branch information
david96182 committed May 8, 2024
1 parent 512e964 commit 4f96ada
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 14 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Ninjemail is a Python library designed to streamline the process of creating ema
- **Customizable Options:** Customize account details such as username, password, first name, last name, country, and birthdate to meet your specific requirements.
- **Error Handling and Logging:** Ninjemail provides error handling capabilities and logs activities to facilitate debugging and tracking of account creation actions.
- **Open-Source and Extensible:** Being an open-source project, Ninjemail encourages contributions and allows for further extension and improvement of its functionalities.
- **Proxy Support:** Ninjemail includes proxy support, giving users the option to use their own proxies for account creation. This feature allows for enhanced privacy, security, and flexibility during the email account creation process.
- **Proxy Support:** Ninjemail includes proxy support, giving users the option to use their own proxies for account creation, including support for authenticated proxies. This feature allows for enhanced privacy, security, and flexibility during the email account creation process.
- **Free Proxy Option:** Additionally, Ninjemail offers an option to automatically retrieve and use free proxies. This feature provides users with a convenient solution for proxy usage, eliminating the need for purchasing or configuring proxies separately.

## Installation
Expand Down Expand Up @@ -114,7 +114,7 @@ The `captcha_keys` parameter is a dictionary that contains the **API keys for su

The `sms_keys` parameter is a dictionary that contains the **API key/s for the SMS service/s**, based on `config.toml`. The default value is an empty dictionary. You can provide an API key or keys for the SMS services if required. Currently, **"getsmscode"**, **"smspool"** and **"5sim"** are supported.

The `proxies` parameter specifies the list of proxy servers to be used for the creation of email accounts. Is optional and can accept either a single proxy server or multiple proxy servers in a list. Each proxy should be provided as a string in the format "http://ip:port," where "ip" represents the IP address of the proxy server and "port" represents the port number.
The `proxies` parameter specifies the list of proxy servers to be used for the creation of email accounts. Is optional and can accept either a single proxy server or multiple proxy servers in a list. Each proxy should be provided as a string in the format "http://ip:port," where "ip" represents the IP address of the proxy server and "port" represents the port number. Additionally, support for authentication proxies is available, but exclusively for chrome and undetected-chrome for the moment. The format for authentication proxies remains the same: "http://username:password@ip:port".

The `auto_proxy` parameter is a boolean flag that determines whether Ninjemail should automatically obtain and rotate free proxies during automation tasks. If `auto_proxy` is set to `True`, Ninjemail will handle the process of acquiring and managing free proxies internally.

Expand Down Expand Up @@ -226,7 +226,7 @@ print(f"Password: {password}")

This will create an Outlook account with the provided information and print the email and password of the created account.

Here's an example that demonstrates how to use Ninjemail to create a Yahoo account without providing any user information. Ninjemail will generate all the necessary data for you, including name, birthdate, etc. This example utilizes smspool as the SMS service and chrome as the web browser:
Here's an example that demonstrates how to use Ninjemail to create a Yahoo account without providing any user information. Ninjemail will generate all the necessary data for you, including name, birthdate, etc. This example utilizes smspool as the SMS service, chrome as the web browser and an authenticated proxy:
```python
from ninjemail import Ninjemail
Expand All @@ -236,7 +236,7 @@ ninja = Ninjemail(
browser="chrome",
captcha_keys={"capsolver": "YOUR_API_KEY"},
sms_keys={"smspool": {"token": "TOKEN"}},
auto_proxy=True)
proxies=['http://username:password@ip_address:port'])
email, password = ninja.create_yahoo_account(
use_proxy=False
)
Expand Down
16 changes: 16 additions & 0 deletions ninjemail/tests/test_webdriver_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ def test_create_undetected_chrome_driver_with_proxy_and_captcha():
assert isinstance(driver, uc.Chrome)
driver.quit()

def test_create_undetected_chrome_driver_with_auth_proxy_and_captcha():
driver = create_driver('undetected-chrome', captcha_extension=True, proxy='http://user:pass@10.10.10.1:2020', captcha_key='test_key')
assert isinstance(driver, uc.Chrome)
driver.quit()

def test_create_undetected_chrome_driver_with_auth_proxy():
driver = create_driver('undetected-chrome', captcha_extension=False, proxy='http://user:pass@10.10.10.1:2020')
assert isinstance(driver, uc.Chrome)
driver.quit()

def test_create_firefox_driver_with_proxy():
proxy_url = 'http://127.0.0.1:8080'
Expand All @@ -88,6 +97,13 @@ def test_create_chrome_driver_with_proxy():
assert isinstance(driver, Chrome)
driver.quit()

def test_create_chrome_driver_with_auth_proxy():
proxy_url = 'http://user:pass@127.0.0.1:8080'

driver = create_driver('chrome', proxy=proxy_url)
assert isinstance(driver, Chrome)
driver.quit()

def test_create_chrome_driver_with_proxy_and_captcha():
driver = create_driver('chrome', captcha_extension=True, proxy='http://10.10.10.1:2020', captcha_key='test_key')
assert isinstance(driver, Chrome)
Expand Down
30 changes: 30 additions & 0 deletions ninjemail/utils/proxy_auth_ext/background.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

var config = {
mode: "fixed_servers",
rules: {
singleProxy: {
scheme: "http",
host: "",
port: parseInt()
},
bypassList: ["localhost"]
}
};

chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});

function callbackFn(details) {
return {
authCredentials: {
username: "",
password: ""
}
};
}

chrome.webRequest.onAuthRequired.addListener(
callbackFn,
{urls: ["<all_urls>"]},
['blocking']
);

19 changes: 19 additions & 0 deletions ninjemail/utils/proxy_auth_ext/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

{
"version": "1.0.0",
"manifest_version": 2,
"name": "Chrome Proxy",
"permissions": [
"proxy",
"tabs",
"unlimitedStorage",
"storage",
"<all_urls>",
"webRequest",
"webRequestBlocking"
],
"background": {
"scripts": ["background.js"]
},
"minimum_chrome_version":"22.0.0"
}
87 changes: 77 additions & 10 deletions ninjemail/utils/webdriver_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import undetected_chromedriver as uc
import os
from urllib.parse import urlparse
import os
import re
import time

Expand All @@ -23,6 +22,49 @@ def add_capsolver_api_key(file_path, api_key):
with open(file_path, 'w') as file:
file.write(updated_content)

def create_backgroundjs(host, port, username, password):
return """
var config = {
mode: "fixed_servers",
rules: {
singleProxy: {
scheme: "http",
host: "%s",
port: parseInt(%s)
},
bypassList: ["localhost"]
}
};
chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});
function callbackFn(details) {
return {
authCredentials: {
username: "%s",
password: "%s"
}
};
}
chrome.webRequest.onAuthRequired.addListener(
callbackFn,
{urls: ["<all_urls>"]},
['blocking']
);
""" % (host, port, username, password)

def create_background_file(background_js):
folder_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'proxy_auth_ext')
file_path = os.path.join(folder_path, 'background.js')

os.makedirs(folder_path, exist_ok=True)

with open(file_path, 'w') as file:
file.write(background_js)

return folder_path

def create_driver(browser, captcha_extension=False, proxy=None, captcha_key=None):
"""
Create a WebDriver instance for the specified browser with optional configurations.
Expand All @@ -45,6 +87,14 @@ def create_driver(browser, captcha_extension=False, proxy=None, captcha_key=None
To create a headless Chrome driver with a proxy and captcha solving extension:
>>> driver = create_driver('chrome', captcha_extension=True, proxy='http://127.0.0.1:8080')
"""
if proxy:
parsed_url = urlparse(proxy)

ip_address = parsed_url.hostname
port = parsed_url.port
username = parsed_url.username
password = parsed_url.password

if browser == 'firefox':
custom_profile = FirefoxProfile()
custom_profile.set_preference("extensions.ui.developer_mode", True)
Expand All @@ -57,11 +107,6 @@ def create_driver(browser, captcha_extension=False, proxy=None, captcha_key=None

# proxy
if proxy:
parsed_url = urlparse(proxy)

ip_address = parsed_url.hostname
port = parsed_url.port

options.set_preference("network.proxy.type", 1)
options.set_preference("network.proxy.http", ip_address)
options.set_preference("network.proxy.http_port", port)
Expand Down Expand Up @@ -95,26 +140,48 @@ def create_driver(browser, captcha_extension=False, proxy=None, captcha_key=None
options.add_experimental_option('prefs', {'intl.accept_languages': 'en-us'})
options.add_argument('--headless=new')
options.add_experimental_option('excludeSwitches', ['enable-logging'])

proxy_ext = None
if proxy:
options.add_argument(f'--proxy-server={proxy}')
if username and password:
background_js = create_backgroundjs(ip_address, port, username, password)
proxy_ext = create_background_file(background_js)
if not captcha_extension:
options.add_argument(f'--load-extension={proxy_ext}')
else:
options.add_argument(f'--proxy-server={proxy}')
if captcha_extension:
add_capsolver_api_key(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'captcha_solvers/capsolver-chrome-extension/assets/config.js'), captcha_key)
ext_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'captcha_solvers/capsolver-chrome-extension/')
options.add_argument(f'--load-extension={ext_path}')
if proxy_ext:
options.add_argument(f'--load-extension={ext_path},{proxy_ext}')
else:
options.add_argument(f'--load-extension={ext_path}')

driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()), options=options)

elif browser == 'undetected-chrome':
options = uc.ChromeOptions()
options.add_argument('--no-sandbox')
options.add_argument('--disable-gpu')
options.add_experimental_option('prefs', {'intl.accept_languages': 'en-us'})

proxy_ext = None
if proxy:
options.add_argument(f'--proxy-server={proxy}')
if username and password:
background_js = create_backgroundjs(ip_address, port, username, password)
proxy_ext = create_background_file(background_js)
if not captcha_extension:
options.add_argument(f'--load-extension={proxy_ext}')
else:
options.add_argument(f'--proxy-server={proxy}')
if captcha_extension:
add_capsolver_api_key(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'captcha_solvers/capsolver-chrome-extension/assets/config.js'), captcha_key)
ext_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'captcha_solvers/capsolver-chrome-extension/')
options.add_argument(f'--load-extension={ext_path}')
if proxy_ext:
options.add_argument(f'--load-extension={ext_path},{proxy_ext}')
else:
options.add_argument(f'--load-extension={ext_path}')

driver = uc.Chrome(options=options, headless=True, use_subprocess=False)
else:
Expand Down

0 comments on commit 4f96ada

Please sign in to comment.