Metadata-Version: 2.4
Name: bulk-email-sender
Version: 0.3.0
Summary: A modular, state-persisting mass email sender library using SMTP — supports multi-account rotation, daily limits, and attachments
Author-email: Jeferson Oliveira Madeira <jeffoliveira977@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/jeffoliveira977/Bulk-email-sender
Project-URL: Repository, https://github.com/jeffoliveira977/Bulk-email-sender
Project-URL: Issues, https://github.com/jeffoliveira977/Bulk-email-sender/issues
Project-URL: Changelog, https://github.com/jeffoliveira977/Bulk-email-sender/releases
Keywords: email,smtp,bulk,sender,automation,newsletter,mass-email
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: Topic :: Communications :: Email
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Operating System :: OS Independent
Classifier: Natural Language :: English
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# Bulk Email Sender

[![PyPI version](https://img.shields.io/pypi/v/bulk-email-sender?color=blue)](https://pypi.org/project/bulk-email-sender/)
[![Python](https://img.shields.io/pypi/pyversions/bulk-email-sender)](https://pypi.org/project/bulk-email-sender/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

A modular, robust, and state-persisting mass email sender library for Python. It supports multiple sender accounts with round-robin rotation, personalized recipient names, automatic daily safety caps, cooldown intervals between emails, attachments, and automatic daily counter resets.

---

## Quick Start

```bash
pip install bulk-email-sender
```
---

## Usage

### CLI

```bash
# Run the campaign (reads config.json from the current directory)
bulk-email-sender

# Reset progress state and start over
bulk-email-sender --reset

# Or run as a module
python -m bulk_email_sender [--reset]
```

### Programmatic

The library never configures logging handlers — it only emits log records via the standard `logging` module. Set up your own handlers before calling `run()`:

```python
import logging
from bulk_email_sender import BulkEmailSender

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    handlers=[
        logging.FileHandler("/var/log/campaign.log", encoding="utf-8"),
        logging.StreamHandler(),
    ],
)

body = """I hope this message finds you well.

I am writing to express my interest in potential job opportunities in IT.
Please find attached my curriculum vitae for your consideration.

Thank you for your time and review.
"""

config = {
    "provider": "gmail",
    "senders": [
        {
            "email": "you@gmail.com",
            "password": "your-app-password",
            "name": "Name",
        },
        {
            "email": "you@yahoo.com",
            "password": "your-app-password-2",
            "name": "Name",
            "provider": "yahoo",
        },
    ],
    "leads_path": "leads.txt",          # .txt or .csv
    "subject": "Your Subject",
    "body": body,
    "attachment_path": "resume.pdf",    # optional, leave "" for none
    "interval_seconds": 60,
    "daily_limit": 450,
    "state_file_path": "/var/log/campaign.json",  # optional, defaults to ./email_state.json
}

BulkEmailSender(config).run()
```

> **Note:** Environment variables `GMAIL_SENDER` and `GMAIL_APP_PASSWORD` override the `"senders"` list at runtime — useful for CI/containerised deployments.

---

## Configuration Reference

| Key | Type | Description |
| :--- | :--- | :--- |
| `provider` | `string` | Default SMTP provider for all senders. See [providers](#smtp-provider-presets). |
| `senders` | `array` | List of sender accounts. At least one is required. |
| `senders[].email` | `string` | Sender email address. |
| `senders[].password` | `string` | App password (not your login password). |
| `senders[].name` | `string` | Display name shown to recipients. |
| `senders[].provider` | `string` | *(optional)* Overrides the global provider for this account. |
| `leads_path` | `string` | Path to the recipients file (`.txt` or `.csv`). |
| `subject` | `string` | Email subject line. |
| `body` | `string` | **Required.** The email body as a plain string. Line breaks (`\n`) are automatically converted to `<br>` in HTML. |
| `attachment_path` | `string` | *(optional)* Path to a file to attach. Leave `""` for none. |
| `interval_seconds` | `number` | Seconds to wait between emails. |
| `daily_limit` | `number` | Maximum emails to send per day. |
| `log_path` | `string` | *(optional)* Relative or absolute path for the log file. Defaults to `./email_sender.log`. |
| `state_file_path` | `string` | *(optional)* Relative or absolute path for the state file. Defaults to `./email_state.json`. |


---

## SMTP Provider Presets

Built-in presets automatically configure the host and port for the chosen `"provider"`:

| Provider Name | Default Host | Port |
| :--- | :--- | :--- |
| `"gmail"` | `smtp.gmail.com` | `587` |
| `"yahoo"` | `smtp.mail.yahoo.com` | `587` |
| `"icloud"` | `smtp.mail.me.com` | `587` |
| `"ZOHO"` | `smtp.zoho.com` | `587` |
| `"GMX"` | `smtp.gmx.com` | `587` |
| `"YANDEX"` | `smtp.yandex.com` | `587` |
| `"AOL"` | `smtp.aol.com` | `587` |

Individual senders can override the global provider by setting their own `"provider"`, `"smtp_host"`, or `"smtp_port"` keys inside the `senders` entry. The library will automatically reconnect with the correct credentials when the active sender changes.

---

## Round-Robin Account Rotation

When multiple accounts are listed in `"senders"`, the library rotates through them in round-robin order (1st email → account 1, 2nd email → account 2, 3rd email → account 1, …). If the rotation switches accounts, the SMTP connection is automatically re-established with the new credentials.

---

---

## Defining Recipient Leads

### Plain Text (`.txt`)

One recipient per line. Name is optional and can be separated by `,` or `;`:

```text
another-recipient@example.com
Jane Doe; jane.doe@example.com
```

### CSV (`.csv`)

Requires an `email` column. An optional `name` column enables personalised greetings:

```csv
name,email
Jane,jane.doe@gmail.com
,another-recipient@example.com
```

When a name is present, the greeting becomes `"Hello Jane,"`. When absent, it defaults to `"Hello,"`.

---

## Email Attachments (Optional)

Set `"attachment_path"` to a file path to attach it to every email.

- **Supported formats:** Any file type (`.pdf`, `.docx`, `.xlsx`, `.zip`, …).
- **Size limit:** Files larger than **25 MB** will abort the campaign before it starts.
- **Missing files:** If the path does not exist, the campaign is aborted with an error.
- **No attachment:** Leave `"attachment_path": ""` or omit the key entirely.

---
