diff --git a/README.md b/README.md index af41748..50e809c 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,498 @@ # MailThunder -MailThunder is a lightweight and flexible email automation tool. It supports SMTP and IMAP4, provides scripting and template features, and makes sending, receiving, and managing email content effortless. -## Notice -- By default, MailThunder uses Google Mail services. You can change the initialization settings to use other providers. -- A configuration file named mail_thunder_content.json must be placed in the current working directory: +[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) +[![Python](https://img.shields.io/badge/python-3.9%2B-blue.svg)](https://www.python.org/) +[![PyPI](https://img.shields.io/pypi/v/je_mail_thunder)](https://pypi.org/project/je-mail-thunder/) -``` json +**MailThunder** is a lightweight and flexible email automation tool for Python. It wraps SMTP and IMAP4 protocols, provides a JSON-based scripting engine and project templates, and makes sending, receiving, and managing email content effortless. + +**[繁體中文](README/README_zh-TW.md)** | **[简体中文](README/README_zh-CN.md)** + +--- + +## Table of Contents + +- [Features](#features) +- [Requirements](#requirements) +- [Installation](#installation) +- [Quick Start](#quick-start) + - [Configuration](#configuration) + - [Sending an Email (SMTP)](#sending-an-email-smtp) + - [Sending an Email with Attachment](#sending-an-email-with-attachment) + - [Reading Emails (IMAP)](#reading-emails-imap) + - [Exporting All Emails to Files](#exporting-all-emails-to-files) +- [Authentication](#authentication) + - [JSON Config File](#json-config-file) + - [Environment Variables](#environment-variables) +- [Scripting Engine](#scripting-engine) + - [Action JSON Format](#action-json-format) + - [Available Script Commands](#available-script-commands) + - [Extending with Custom Commands](#extending-with-custom-commands) + - [Dynamic Package Loading](#dynamic-package-loading) +- [Project Templates](#project-templates) +- [Command-Line Interface](#command-line-interface) +- [Socket Server](#socket-server) +- [API Reference](#api-reference) + - [SMTPWrapper](#smtpwrapper) + - [IMAPWrapper](#imapwrapper) + - [Executor Functions](#executor-functions) + - [Utility Functions](#utility-functions) +- [Project Structure](#project-structure) +- [License](#license) + +--- + +## Features + +- **SMTP support** — Send emails via SSL with Gmail (default) or any SMTP provider +- **IMAP4 support** — Read, search, and export emails via IMAP4 SSL +- **Attachment handling** — Automatically detect MIME types for text, image, audio, and binary files +- **HTML email** — Send HTML-formatted emails with attachments +- **JSON scripting engine** — Automate email workflows using JSON action files +- **Project templates** — Scaffold projects with pre-built keyword and executor templates +- **Socket server** — Control MailThunder remotely via TCP socket commands +- **Package manager** — Dynamically load Python packages into the scripting executor +- **Environment variable auth** — Authenticate via config file or OS environment variables +- **Auto-export** — Export all mailbox emails to local files in one call +- **Context manager support** — Use `with` statement for both SMTP and IMAP connections +- **Logging** — Built-in logging for all operations + +--- + +## Requirements + +- Python 3.9 or later + +--- + +## Installation + +**Stable release:** + +```bash +pip install je_mail_thunder +``` + +**Development release:** + +```bash +pip install je_mail_thunder_dev +``` + +--- + +## Quick Start + +### Configuration + +Before using MailThunder, you need to set up authentication. Create a file named `mail_thunder_content.json` in your current working directory: + +```json { - "user": "example@gmail.com", - "password": "password" + "user": "your_email@gmail.com", + "password": "your_app_password" } ``` -- Set up an application-specific password: - - https://support.google.com/accounts/answer/185833 -- Enable IMAP: - - https://support.google.com/mail/answer/7126229?hl=en -## Key features: -- Fast email automation -- SMTP support -- IMAP4 support -- MailThunder scripting -- Automatic export of all email content to files -- Automated email sending -- Automated file sending -- Socket server support -- Script project & template support +> **Important:** If you are using Gmail, you must use an [App Password](https://support.google.com/accounts/answer/185833), not your regular Google account password. You also need to [enable IMAP](https://support.google.com/mail/answer/7126229?hl=en) in your Gmail settings. + +### Sending an Email (SMTP) -## Installation +```python +from je_mail_thunder import SMTPWrapper +with SMTPWrapper() as smtp: + smtp.later_init() # Log in using config file or env vars + smtp.create_message_and_send( + message_content="Hello from MailThunder!", + message_setting_dict={ + "Subject": "Test Email", + "From": "sender@gmail.com", + "To": "receiver@gmail.com" + } + ) ``` -pip install je_mail_thunder + +### Sending an Email with Attachment + +```python +from je_mail_thunder import SMTPWrapper + +with SMTPWrapper() as smtp: + smtp.later_init() + smtp.create_message_with_attach_and_send( + message_content="Please see the attached file.", + message_setting_dict={ + "Subject": "Email with Attachment", + "From": "sender@gmail.com", + "To": "receiver@gmail.com" + }, + attach_file="/path/to/file.pdf", + use_html=False # Set True if message_content is HTML + ) ``` -## Requires -- Python 3.9 or later \ No newline at end of file +### Reading Emails (IMAP) + +```python +from je_mail_thunder import IMAPWrapper + +with IMAPWrapper() as imap: + imap.later_init() # Log in + imap.select_mailbox("INBOX") + emails = imap.mail_content_list() + for mail in emails: + print(f"Subject: {mail['SUBJECT']}") + print(f"From: {mail['FROM']}") + print(f"Body: {mail['BODY'][:100]}...") +``` + +### Exporting All Emails to Files + +```python +from je_mail_thunder import IMAPWrapper + +with IMAPWrapper() as imap: + imap.later_init() + imap.select_mailbox("INBOX") + imap.output_all_mail_as_file() # Saves each email as a file named by subject +``` + +--- + +## Authentication + +MailThunder supports two authentication methods. It tries the JSON config file first, then falls back to environment variables. + +### JSON Config File + +Place `mail_thunder_content.json` in the current working directory: + +```json +{ + "user": "your_email@gmail.com", + "password": "your_app_password" +} +``` + +### Environment Variables + +Set these environment variables before running your script: + +```python +from je_mail_thunder import set_mail_thunder_os_environ + +set_mail_thunder_os_environ( + mail_thunder_user="your_email@gmail.com", + mail_thunder_user_password="your_app_password" +) +``` + +Or set them in your shell: + +```bash +export mail_thunder_user="your_email@gmail.com" +export mail_thunder_user_password="your_app_password" +``` + +--- + +## Scripting Engine + +MailThunder includes a JSON-based scripting engine that lets you automate email workflows without writing Python code. + +### Action JSON Format + +Action files use a list of commands. Each command is an array where the first element is the command name and the optional second element contains the arguments: + +```json +{ + "auto_control": [ + ["command_name"], + ["command_name", {"key": "value"}], + ["command_name", ["arg1", "arg2"]] + ] +} +``` + +- Use a **dict** `{}` as the second element for keyword arguments (`**kwargs`) +- Use a **list** `[]` as the second element for positional arguments (`*args`) +- Use only the command name (no second element) for commands with no arguments + +### Available Script Commands + +| Command | Description | Arguments | +|---------|-------------|-----------| +| `MT_smtp_later_init` | Initialize and log in to SMTP | None | +| `MT_smtp_create_message_and_send` | Create and send an email | `{"message_content": str, "message_setting_dict": dict}` | +| `MT_smtp_create_message_with_attach_and_send` | Create and send an email with attachment | `{"message_content": str, "message_setting_dict": dict, "attach_file": str, "use_html": bool}` | +| `smtp_quit` | Disconnect from SMTP server | None | +| `MT_imap_later_init` | Initialize and log in to IMAP | None | +| `MT_imap_select_mailbox` | Select a mailbox | `{"mailbox": str, "readonly": bool}` (default: INBOX) | +| `MT_imap_search_mailbox` | Search and get mail details | `{"search_str": str, "charset": str}` | +| `MT_imap_mail_content_list` | Get all mail content as list | `{"search_str": str, "charset": str}` | +| `MT_imap_output_all_mail_as_file` | Export all emails to files | `{"search_str": str, "charset": str}` | +| `MT_imap_quit` | Disconnect from IMAP server | None | +| `MT_set_mail_thunder_os_environ` | Set auth env vars | `{"mail_thunder_user": str, "mail_thunder_user_password": str}` | +| `MT_get_mail_thunder_os_environ` | Get auth env vars | None | +| `MT_add_package_to_executor` | Load a Python package into executor | `["package_name"]` | + +**Example — Send an email via JSON script:** + +```json +{ + "auto_control": [ + ["MT_smtp_later_init"], + ["MT_smtp_create_message_and_send", { + "message_content": "Hello World!", + "message_setting_dict": { + "Subject": "Automated Email", + "To": "receiver@gmail.com", + "From": "sender@gmail.com" + } + }], + ["smtp_quit"] + ] +} +``` + +**Example — Read and export all emails:** + +```json +{ + "auto_control": [ + ["MT_imap_later_init"], + ["MT_imap_select_mailbox"], + ["MT_imap_output_all_mail_as_file"] + ] +} +``` + +### Extending with Custom Commands + +You can add your own functions to the scripting executor: + +```python +from je_mail_thunder import add_command_to_executor + +def my_custom_function(param1, param2): + print(f"Custom: {param1}, {param2}") + +add_command_to_executor({"my_command": my_custom_function}) +``` + +Then use `"my_command"` in your JSON action files. + +### Dynamic Package Loading + +Load any installed Python package into the executor at runtime: + +```json +{ + "auto_control": [ + ["MT_add_package_to_executor", ["os"]], + ["os_system", ["echo Hello from os.system"]] + ] +} +``` + +This loads all functions, builtins, and classes from the specified package, prefixed with `packagename_`. + +> **Warning:** Loading packages like `os` into the executor can be a security risk. Only load trusted packages and validate all inputs. + +--- + +## Project Templates + +MailThunder can scaffold a project with pre-built templates: + +```python +from je_mail_thunder import create_project_dir + +create_project_dir() # Creates in current directory +# or +create_project_dir(project_path="/path/to/project", parent_name="MyMailProject") +``` + +This creates the following structure: + +``` +MyMailProject/ + keyword/ + keyword1.json # SMTP send email template + keyword2.json # IMAP read and export template + bad_keyword_1.json # Package loading example (security warning) + executor/ + executor_one_file.py # Execute a single action file + executor_folder.py # Execute all action files in a directory + executor_bad_file.py # Bad practice example +``` + +--- + +## Command-Line Interface + +MailThunder provides a CLI via `python -m je_mail_thunder`: + +```bash +# Execute a single JSON action file +python -m je_mail_thunder -e /path/to/action.json + +# Execute all JSON action files in a directory +python -m je_mail_thunder -d /path/to/actions/ + +# Execute a JSON string directly +python -m je_mail_thunder --execute_str '[["MT_smtp_later_init"], ["smtp_quit"]]' + +# Create a new project with templates +python -m je_mail_thunder -c /path/to/project +``` + +| Flag | Long Flag | Description | +|------|-----------|-------------| +| `-e` | `--execute_file` | Execute a single JSON action file | +| `-d` | `--execute_dir` | Execute all JSON action files in a directory | +| `-c` | `--create_project` | Create a project with templates | +| | `--execute_str` | Execute a JSON string directly | + +--- + +## Socket Server + +MailThunder includes a TCP socket server that accepts JSON commands remotely: + +```python +from je_mail_thunder.utils.socket_server.mail_thunder_socket_server import start_autocontrol_socket_server + +server = start_autocontrol_socket_server(host="localhost", port=9944) +# Server is now running in a background thread +``` + +**Sending commands to the server:** + +```python +import socket +import json + +client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +client.connect(("localhost", 9944)) + +# Send an action command +command = json.dumps([["MT_smtp_later_init"], ["smtp_quit"]]) +client.send(command.encode("utf-8")) + +# Receive response +response = client.recv(8192).decode("utf-8") +print(response) + +client.close() +``` + +Send `"quit_server"` to shut down the server. + +--- + +## API Reference + +### SMTPWrapper + +Extends `smtplib.SMTP_SSL`. Default host: `smtp.gmail.com`, default port: `465`. + +| Method | Description | +|--------|-------------| +| `later_init()` | Log in using config file or environment variables | +| `create_message(message_content, message_setting_dict, **kwargs)` | Create an `EmailMessage` object | +| `create_message_with_attach(message_content, message_setting_dict, attach_file, use_html=False)` | Create a `MIMEMultipart` message with attachment | +| `create_message_and_send(message_content, message_setting_dict, **kwargs)` | Create and immediately send an email | +| `create_message_with_attach_and_send(message_content, message_setting_dict, attach_file, use_html=False)` | Create and send an email with attachment | +| `try_to_login_with_env_or_content()` | Attempt login from config or env vars, returns `bool` | +| `quit()` | Disconnect and close | + +**Using a different SMTP provider:** + +```python +from je_mail_thunder import SMTPWrapper + +# Example: Outlook +smtp = SMTPWrapper(host="smtp.office365.com", port=587) +``` + +### IMAPWrapper + +Extends `imaplib.IMAP4_SSL`. Default host: `imap.gmail.com`. + +| Method | Description | +|--------|-------------| +| `later_init()` | Log in using config file or environment variables | +| `select_mailbox(mailbox="INBOX", readonly=False)` | Select a mailbox, returns `bool` | +| `search_mailbox(search_str="ALL", charset=None)` | Search and return raw mail details as list | +| `mail_content_list(search_str="ALL", charset=None)` | Return parsed mail content as list of dicts | +| `output_all_mail_as_file(search_str="ALL", charset=None)` | Export all emails to files named by subject | +| `quit()` | Close mailbox and logout | + +**Mail content dict format:** + +```python +{ + "SUBJECT": "Email subject", + "FROM": "sender@example.com", + "TO": "receiver@example.com", + "BODY": "Email body content..." +} +``` + +### Executor Functions + +| Function | Description | +|----------|-------------| +| `execute_action(action_list)` | Execute a list of action commands | +| `execute_files(execute_files_list)` | Execute multiple JSON action files | +| `add_command_to_executor(command_dict)` | Add custom functions to the executor | +| `read_action_json(file_path)` | Read a JSON action file | + +### Utility Functions + +| Function | Description | +|----------|-------------| +| `create_project_dir(project_path, parent_name)` | Create a project with templates | +| `set_mail_thunder_os_environ(user, password)` | Set authentication environment variables | +| `get_mail_thunder_os_environ()` | Get authentication environment variables | +| `read_output_content()` | Read `mail_thunder_content.json` from cwd | +| `write_output_content()` | Write content data to `mail_thunder_content.json` | +| `get_dir_files_as_list(path)` | Get all files in a directory as list | + +--- + +## Project Structure + +``` +MailThunder/ + je_mail_thunder/ + __init__.py # Public API exports + __main__.py # CLI entry point + smtp/ + smtp_wrapper.py # SMTPWrapper class + imap/ + imap_wrapper.py # IMAPWrapper class + utils/ + exception/ # Custom exceptions and error tags + executor/ # JSON scripting engine + file_process/ # File utility functions + json/ # JSON file read/write + json_format/ # JSON formatting + logging/ # Logger instance + package_manager/ # Dynamic package loader + project/ # Project template scaffolding + save_mail_user_content/ # Auth config and env var handling + socket_server/ # TCP socket server + test/ # Unit tests + docs/ # Sphinx documentation +``` + +--- + +## License + +This project is licensed under the [MIT License](LICENSE). + +Copyright (c) 2021 JE-Chen diff --git a/README/README_zh-CN.md b/README/README_zh-CN.md new file mode 100644 index 0000000..0ce2a62 --- /dev/null +++ b/README/README_zh-CN.md @@ -0,0 +1,498 @@ +# MailThunder + +[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](../LICENSE) +[![Python](https://img.shields.io/badge/python-3.9%2B-blue.svg)](https://www.python.org/) +[![PyPI](https://img.shields.io/pypi/v/je_mail_thunder)](https://pypi.org/project/je-mail-thunder/) + +**MailThunder** 是一款轻量且灵活的 Python 电子邮件自动化工具。它封装了 SMTP 和 IMAP4 协议,提供 JSON 脚本引擎与项目模板功能,让发信、收信与管理邮件内容变得轻松简单。 + +**[English](../README.md)** | **[繁體中文](README_zh-TW.md)** + +--- + +## 目录 + +- [功能特色](#功能特色) +- [系统需求](#系统需求) +- [安装](#安装) +- [快速开始](#快速开始) + - [配置](#配置) + - [发送邮件 (SMTP)](#发送邮件-smtp) + - [发送带附件的邮件](#发送带附件的邮件) + - [读取邮件 (IMAP)](#读取邮件-imap) + - [导出所有邮件为文件](#导出所有邮件为文件) +- [身份验证](#身份验证) + - [JSON 配置文件](#json-配置文件) + - [环境变量](#环境变量) +- [脚本引擎](#脚本引擎) + - [Action JSON 格式](#action-json-格式) + - [可用的脚本指令](#可用的脚本指令) + - [扩展自定义指令](#扩展自定义指令) + - [动态加载包](#动态加载包) +- [项目模板](#项目模板) +- [命令行界面](#命令行界面) +- [Socket 服务器](#socket-服务器) +- [API 参考](#api-参考) + - [SMTPWrapper](#smtpwrapper) + - [IMAPWrapper](#imapwrapper) + - [Executor 函数](#executor-函数) + - [工具函数](#工具函数) +- [项目结构](#项目结构) +- [许可证](#许可证) + +--- + +## 功能特色 + +- **SMTP 支持** — 通过 SSL 发送邮件,默认使用 Gmail,也可自定义其他 SMTP 服务 +- **IMAP4 支持** — 通过 IMAP4 SSL 读取、搜索和导出邮件 +- **附件处理** — 自动检测文本、图片、音频和二进制文件的 MIME 类型 +- **HTML 邮件** — 支持发送 HTML 格式的邮件与附件 +- **JSON 脚本引擎** — 使用 JSON 动作文件自动化邮件工作流程 +- **项目模板** — 快速创建包含预设关键字和执行器模板的项目 +- **Socket 服务器** — 通过 TCP Socket 远程控制 MailThunder +- **包管理器** — 动态加载 Python 包至脚本执行器 +- **环境变量验证** — 支持配置文件或操作系统环境变量进行身份验证 +- **自动导出** — 一行指令即可将邮箱所有邮件导出为本地文件 +- **Context Manager 支持** — SMTP 和 IMAP 连接均可使用 `with` 语法 +- **日志记录** — 内置所有操作的日志记录 + +--- + +## 系统需求 + +- Python 3.9 或更新版本 + +--- + +## 安装 + +**稳定版:** + +```bash +pip install je_mail_thunder +``` + +**开发版:** + +```bash +pip install je_mail_thunder_dev +``` + +--- + +## 快速开始 + +### 配置 + +使用 MailThunder 之前,需要先配置身份验证。在当前工作目录下创建一个名为 `mail_thunder_content.json` 的文件: + +```json +{ + "user": "your_email@gmail.com", + "password": "your_app_password" +} +``` + +> **重要提示:** 若使用 Gmail,必须使用[应用专用密码](https://support.google.com/accounts/answer/185833),而非普通的 Google 账户密码。同时需要在 Gmail 设置中[启用 IMAP](https://support.google.com/mail/answer/7126229?hl=zh-Hans)。 + +### 发送邮件 (SMTP) + +```python +from je_mail_thunder import SMTPWrapper + +with SMTPWrapper() as smtp: + smtp.later_init() # 使用配置文件或环境变量登录 + smtp.create_message_and_send( + message_content="来自 MailThunder 的问候!", + message_setting_dict={ + "Subject": "测试邮件", + "From": "sender@gmail.com", + "To": "receiver@gmail.com" + } + ) +``` + +### 发送带附件的邮件 + +```python +from je_mail_thunder import SMTPWrapper + +with SMTPWrapper() as smtp: + smtp.later_init() + smtp.create_message_with_attach_and_send( + message_content="请查看附件。", + message_setting_dict={ + "Subject": "带附件的邮件", + "From": "sender@gmail.com", + "To": "receiver@gmail.com" + }, + attach_file="/path/to/file.pdf", + use_html=False # 若 message_content 为 HTML 则设为 True + ) +``` + +### 读取邮件 (IMAP) + +```python +from je_mail_thunder import IMAPWrapper + +with IMAPWrapper() as imap: + imap.later_init() # 登录 + imap.select_mailbox("INBOX") + emails = imap.mail_content_list() + for mail in emails: + print(f"主题: {mail['SUBJECT']}") + print(f"发件人: {mail['FROM']}") + print(f"内容: {mail['BODY'][:100]}...") +``` + +### 导出所有邮件为文件 + +```python +from je_mail_thunder import IMAPWrapper + +with IMAPWrapper() as imap: + imap.later_init() + imap.select_mailbox("INBOX") + imap.output_all_mail_as_file() # 以邮件主题为文件名保存每封邮件 +``` + +--- + +## 身份验证 + +MailThunder 支持两种身份验证方式。它会先尝试 JSON 配置文件,若找不到则回退至环境变量。 + +### JSON 配置文件 + +在当前工作目录下放置 `mail_thunder_content.json`: + +```json +{ + "user": "your_email@gmail.com", + "password": "your_app_password" +} +``` + +### 环境变量 + +在运行脚本前设置以下环境变量: + +```python +from je_mail_thunder import set_mail_thunder_os_environ + +set_mail_thunder_os_environ( + mail_thunder_user="your_email@gmail.com", + mail_thunder_user_password="your_app_password" +) +``` + +或在 Shell 中设置: + +```bash +export mail_thunder_user="your_email@gmail.com" +export mail_thunder_user_password="your_app_password" +``` + +--- + +## 脚本引擎 + +MailThunder 内置 JSON 脚本引擎,让你无需编写 Python 代码即可自动化邮件工作流程。 + +### Action JSON 格式 + +动作文件使用指令列表格式。每个指令为一个数组,第一个元素为指令名称,可选的第二个元素为参数: + +```json +{ + "auto_control": [ + ["指令名称"], + ["指令名称", {"key": "value"}], + ["指令名称", ["arg1", "arg2"]] + ] +} +``` + +- 使用 **dict** `{}` 作为第二个元素传递关键字参数(`**kwargs`) +- 使用 **list** `[]` 作为第二个元素传递位置参数(`*args`) +- 只写指令名称(不含第二个元素)表示无参数指令 + +### 可用的脚本指令 + +| 指令 | 说明 | 参数 | +|------|------|------| +| `MT_smtp_later_init` | 初始化并登录 SMTP | 无 | +| `MT_smtp_create_message_and_send` | 创建并发送邮件 | `{"message_content": str, "message_setting_dict": dict}` | +| `MT_smtp_create_message_with_attach_and_send` | 创建并发送带附件的邮件 | `{"message_content": str, "message_setting_dict": dict, "attach_file": str, "use_html": bool}` | +| `smtp_quit` | 断开 SMTP 连接 | 无 | +| `MT_imap_later_init` | 初始化并登录 IMAP | 无 | +| `MT_imap_select_mailbox` | 选择邮箱 | `{"mailbox": str, "readonly": bool}`(默认:INBOX)| +| `MT_imap_search_mailbox` | 搜索并获取邮件详细信息 | `{"search_str": str, "charset": str}` | +| `MT_imap_mail_content_list` | 获取所有邮件内容列表 | `{"search_str": str, "charset": str}` | +| `MT_imap_output_all_mail_as_file` | 导出所有邮件为文件 | `{"search_str": str, "charset": str}` | +| `MT_imap_quit` | 断开 IMAP 连接 | 无 | +| `MT_set_mail_thunder_os_environ` | 设置验证环境变量 | `{"mail_thunder_user": str, "mail_thunder_user_password": str}` | +| `MT_get_mail_thunder_os_environ` | 获取验证环境变量 | 无 | +| `MT_add_package_to_executor` | 加载 Python 包至执行器 | `["包名称"]` | + +**示例 — 通过 JSON 脚本发送邮件:** + +```json +{ + "auto_control": [ + ["MT_smtp_later_init"], + ["MT_smtp_create_message_and_send", { + "message_content": "Hello World!", + "message_setting_dict": { + "Subject": "自动化邮件", + "To": "receiver@gmail.com", + "From": "sender@gmail.com" + } + }], + ["smtp_quit"] + ] +} +``` + +**示例 — 读取并导出所有邮件:** + +```json +{ + "auto_control": [ + ["MT_imap_later_init"], + ["MT_imap_select_mailbox"], + ["MT_imap_output_all_mail_as_file"] + ] +} +``` + +### 扩展自定义指令 + +你可以将自己的函数加入脚本执行器: + +```python +from je_mail_thunder import add_command_to_executor + +def my_custom_function(param1, param2): + print(f"自定义指令: {param1}, {param2}") + +add_command_to_executor({"my_command": my_custom_function}) +``` + +之后即可在 JSON 动作文件中使用 `"my_command"`。 + +### 动态加载包 + +在运行时动态加载任何已安装的 Python 包至执行器: + +```json +{ + "auto_control": [ + ["MT_add_package_to_executor", ["os"]], + ["os_system", ["echo Hello from os.system"]] + ] +} +``` + +这会加载指定包的所有函数、内置功能和类,并以 `包名称_` 为前缀。 + +> **警告:** 将 `os` 等包加载至执行器可能存在安全风险。请仅加载可信任的包并验证所有输入。 + +--- + +## 项目模板 + +MailThunder 可以快速创建包含预设模板的项目: + +```python +from je_mail_thunder import create_project_dir + +create_project_dir() # 在当前目录创建 +# 或 +create_project_dir(project_path="/path/to/project", parent_name="MyMailProject") +``` + +创建的目录结构如下: + +``` +MyMailProject/ + keyword/ + keyword1.json # SMTP 发送邮件模板 + keyword2.json # IMAP 读取并导出模板 + bad_keyword_1.json # 包加载示例(安全性警告) + executor/ + executor_one_file.py # 执行单一动作文件 + executor_folder.py # 执行目录内所有动作文件 + executor_bad_file.py # 不良实践示例 +``` + +--- + +## 命令行界面 + +MailThunder 通过 `python -m je_mail_thunder` 提供命令行界面: + +```bash +# 执行单一 JSON 动作文件 +python -m je_mail_thunder -e /path/to/action.json + +# 执行目录内所有 JSON 动作文件 +python -m je_mail_thunder -d /path/to/actions/ + +# 直接执行 JSON 字符串 +python -m je_mail_thunder --execute_str '[["MT_smtp_later_init"], ["smtp_quit"]]' + +# 创建包含模板的新项目 +python -m je_mail_thunder -c /path/to/project +``` + +| 标志 | 完整标志 | 说明 | +|------|----------|------| +| `-e` | `--execute_file` | 执行单一 JSON 动作文件 | +| `-d` | `--execute_dir` | 执行目录内所有 JSON 动作文件 | +| `-c` | `--create_project` | 创建包含模板的项目 | +| | `--execute_str` | 直接执行 JSON 字符串 | + +--- + +## Socket 服务器 + +MailThunder 内置 TCP Socket 服务器,可接收远程 JSON 指令: + +```python +from je_mail_thunder.utils.socket_server.mail_thunder_socket_server import start_autocontrol_socket_server + +server = start_autocontrol_socket_server(host="localhost", port=9944) +# 服务器现在在后台线程中运行 +``` + +**向服务器发送指令:** + +```python +import socket +import json + +client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +client.connect(("localhost", 9944)) + +# 发送动作指令 +command = json.dumps([["MT_smtp_later_init"], ["smtp_quit"]]) +client.send(command.encode("utf-8")) + +# 接收响应 +response = client.recv(8192).decode("utf-8") +print(response) + +client.close() +``` + +发送 `"quit_server"` 可关闭服务器。 + +--- + +## API 参考 + +### SMTPWrapper + +继承自 `smtplib.SMTP_SSL`。默认主机:`smtp.gmail.com`,默认端口:`465`。 + +| 方法 | 说明 | +|------|------| +| `later_init()` | 使用配置文件或环境变量登录 | +| `create_message(message_content, message_setting_dict, **kwargs)` | 创建 `EmailMessage` 对象 | +| `create_message_with_attach(message_content, message_setting_dict, attach_file, use_html=False)` | 创建带附件的 `MIMEMultipart` 消息 | +| `create_message_and_send(message_content, message_setting_dict, **kwargs)` | 创建并立即发送邮件 | +| `create_message_with_attach_and_send(message_content, message_setting_dict, attach_file, use_html=False)` | 创建并发送带附件的邮件 | +| `try_to_login_with_env_or_content()` | 尝试从配置文件或环境变量登录,返回 `bool` | +| `quit()` | 断开连接并关闭 | + +**使用其他 SMTP 服务商:** + +```python +from je_mail_thunder import SMTPWrapper + +# 示例:Outlook +smtp = SMTPWrapper(host="smtp.office365.com", port=587) +``` + +### IMAPWrapper + +继承自 `imaplib.IMAP4_SSL`。默认主机:`imap.gmail.com`。 + +| 方法 | 说明 | +|------|------| +| `later_init()` | 使用配置文件或环境变量登录 | +| `select_mailbox(mailbox="INBOX", readonly=False)` | 选择邮箱,返回 `bool` | +| `search_mailbox(search_str="ALL", charset=None)` | 搜索并返回原始邮件详细信息列表 | +| `mail_content_list(search_str="ALL", charset=None)` | 返回已解析的邮件内容字典列表 | +| `output_all_mail_as_file(search_str="ALL", charset=None)` | 以主题为文件名导出所有邮件 | +| `quit()` | 关闭邮箱并登出 | + +**邮件内容字典格式:** + +```python +{ + "SUBJECT": "邮件主题", + "FROM": "sender@example.com", + "TO": "receiver@example.com", + "BODY": "邮件内容..." +} +``` + +### Executor 函数 + +| 函数 | 说明 | +|------|------| +| `execute_action(action_list)` | 执行动作指令列表 | +| `execute_files(execute_files_list)` | 执行多个 JSON 动作文件 | +| `add_command_to_executor(command_dict)` | 将自定义函数加入执行器 | +| `read_action_json(file_path)` | 读取 JSON 动作文件 | + +### 工具函数 + +| 函数 | 说明 | +|------|------| +| `create_project_dir(project_path, parent_name)` | 创建包含模板的项目 | +| `set_mail_thunder_os_environ(user, password)` | 设置验证环境变量 | +| `get_mail_thunder_os_environ()` | 获取验证环境变量 | +| `read_output_content()` | 从当前工作目录读取 `mail_thunder_content.json` | +| `write_output_content()` | 将内容数据写入 `mail_thunder_content.json` | +| `get_dir_files_as_list(path)` | 获取目录内所有文件列表 | + +--- + +## 项目结构 + +``` +MailThunder/ + je_mail_thunder/ + __init__.py # 公开 API 导出 + __main__.py # CLI 入口点 + smtp/ + smtp_wrapper.py # SMTPWrapper 类 + imap/ + imap_wrapper.py # IMAPWrapper 类 + utils/ + exception/ # 自定义异常与错误标签 + executor/ # JSON 脚本引擎 + file_process/ # 文件工具函数 + json/ # JSON 文件读写 + json_format/ # JSON 格式化 + logging/ # 日志实例 + package_manager/ # 动态包加载器 + project/ # 项目模板创建 + save_mail_user_content/ # 验证配置与环境变量处理 + socket_server/ # TCP Socket 服务器 + test/ # 单元测试 + docs/ # Sphinx 文档 +``` + +--- + +## 许可证 + +本项目采用 [MIT 许可证](../LICENSE)。 + +Copyright (c) 2021 JE-Chen diff --git a/README/README_zh-TW.md b/README/README_zh-TW.md new file mode 100644 index 0000000..48e99f3 --- /dev/null +++ b/README/README_zh-TW.md @@ -0,0 +1,498 @@ +# MailThunder + +[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](../LICENSE) +[![Python](https://img.shields.io/badge/python-3.9%2B-blue.svg)](https://www.python.org/) +[![PyPI](https://img.shields.io/pypi/v/je_mail_thunder)](https://pypi.org/project/je-mail-thunder/) + +**MailThunder** 是一款輕量且靈活的 Python 電子郵件自動化工具。它封裝了 SMTP 和 IMAP4 協定,提供 JSON 腳本引擎與專案模板功能,讓寄信、收信與管理郵件內容變得輕鬆簡單。 + +**[English](../README.md)** | **[简体中文](README_zh-CN.md)** + +--- + +## 目錄 + +- [功能特色](#功能特色) +- [系統需求](#系統需求) +- [安裝](#安裝) +- [快速開始](#快速開始) + - [設定](#設定) + - [寄送郵件 (SMTP)](#寄送郵件-smtp) + - [寄送帶附件的郵件](#寄送帶附件的郵件) + - [讀取郵件 (IMAP)](#讀取郵件-imap) + - [匯出所有郵件為檔案](#匯出所有郵件為檔案) +- [身份驗證](#身份驗證) + - [JSON 設定檔](#json-設定檔) + - [環境變數](#環境變數) +- [腳本引擎](#腳本引擎) + - [Action JSON 格式](#action-json-格式) + - [可用的腳本指令](#可用的腳本指令) + - [擴充自訂指令](#擴充自訂指令) + - [動態載入套件](#動態載入套件) +- [專案模板](#專案模板) +- [命令列介面](#命令列介面) +- [Socket 伺服器](#socket-伺服器) +- [API 參考](#api-參考) + - [SMTPWrapper](#smtpwrapper) + - [IMAPWrapper](#imapwrapper) + - [Executor 函式](#executor-函式) + - [工具函式](#工具函式) +- [專案結構](#專案結構) +- [授權條款](#授權條款) + +--- + +## 功能特色 + +- **SMTP 支援** — 透過 SSL 寄送郵件,預設使用 Gmail,也可自訂其他 SMTP 服務 +- **IMAP4 支援** — 透過 IMAP4 SSL 讀取、搜尋和匯出郵件 +- **附件處理** — 自動偵測文字、圖片、音訊和二進位檔案的 MIME 類型 +- **HTML 郵件** — 支援寄送 HTML 格式的郵件與附件 +- **JSON 腳本引擎** — 使用 JSON 動作檔自動化郵件工作流程 +- **專案模板** — 快速建立包含預設關鍵字和執行器模板的專案 +- **Socket 伺服器** — 透過 TCP Socket 遠端控制 MailThunder +- **套件管理器** — 動態載入 Python 套件至腳本執行器 +- **環境變數驗證** — 支援設定檔或作業系統環境變數進行身份驗證 +- **自動匯出** — 一行指令即可將信箱所有郵件匯出為本機檔案 +- **Context Manager 支援** — SMTP 和 IMAP 連線皆可使用 `with` 語法 +- **日誌記錄** — 內建所有操作的日誌紀錄 + +--- + +## 系統需求 + +- Python 3.9 或更新版本 + +--- + +## 安裝 + +**穩定版:** + +```bash +pip install je_mail_thunder +``` + +**開發版:** + +```bash +pip install je_mail_thunder_dev +``` + +--- + +## 快速開始 + +### 設定 + +使用 MailThunder 之前,需要先設定身份驗證。在目前工作目錄下建立一個名為 `mail_thunder_content.json` 的檔案: + +```json +{ + "user": "your_email@gmail.com", + "password": "your_app_password" +} +``` + +> **重要提示:** 若使用 Gmail,必須使用[應用程式密碼](https://support.google.com/accounts/answer/185833),而非一般的 Google 帳戶密碼。同時需要在 Gmail 設定中[啟用 IMAP](https://support.google.com/mail/answer/7126229?hl=zh-Hant)。 + +### 寄送郵件 (SMTP) + +```python +from je_mail_thunder import SMTPWrapper + +with SMTPWrapper() as smtp: + smtp.later_init() # 使用設定檔或環境變數登入 + smtp.create_message_and_send( + message_content="來自 MailThunder 的問候!", + message_setting_dict={ + "Subject": "測試郵件", + "From": "sender@gmail.com", + "To": "receiver@gmail.com" + } + ) +``` + +### 寄送帶附件的郵件 + +```python +from je_mail_thunder import SMTPWrapper + +with SMTPWrapper() as smtp: + smtp.later_init() + smtp.create_message_with_attach_and_send( + message_content="請查看附件。", + message_setting_dict={ + "Subject": "帶附件的郵件", + "From": "sender@gmail.com", + "To": "receiver@gmail.com" + }, + attach_file="/path/to/file.pdf", + use_html=False # 若 message_content 為 HTML 則設為 True + ) +``` + +### 讀取郵件 (IMAP) + +```python +from je_mail_thunder import IMAPWrapper + +with IMAPWrapper() as imap: + imap.later_init() # 登入 + imap.select_mailbox("INBOX") + emails = imap.mail_content_list() + for mail in emails: + print(f"主旨: {mail['SUBJECT']}") + print(f"寄件者: {mail['FROM']}") + print(f"內容: {mail['BODY'][:100]}...") +``` + +### 匯出所有郵件為檔案 + +```python +from je_mail_thunder import IMAPWrapper + +with IMAPWrapper() as imap: + imap.later_init() + imap.select_mailbox("INBOX") + imap.output_all_mail_as_file() # 以郵件主旨為檔名儲存每封郵件 +``` + +--- + +## 身份驗證 + +MailThunder 支援兩種身份驗證方式。它會先嘗試 JSON 設定檔,若找不到則回退至環境變數。 + +### JSON 設定檔 + +在目前工作目錄下放置 `mail_thunder_content.json`: + +```json +{ + "user": "your_email@gmail.com", + "password": "your_app_password" +} +``` + +### 環境變數 + +在執行腳本前設定以下環境變數: + +```python +from je_mail_thunder import set_mail_thunder_os_environ + +set_mail_thunder_os_environ( + mail_thunder_user="your_email@gmail.com", + mail_thunder_user_password="your_app_password" +) +``` + +或在 Shell 中設定: + +```bash +export mail_thunder_user="your_email@gmail.com" +export mail_thunder_user_password="your_app_password" +``` + +--- + +## 腳本引擎 + +MailThunder 內建 JSON 腳本引擎,讓你無需撰寫 Python 程式碼即可自動化郵件工作流程。 + +### Action JSON 格式 + +動作檔使用指令列表格式。每個指令為一個陣列,第一個元素為指令名稱,可選的第二個元素為參數: + +```json +{ + "auto_control": [ + ["指令名稱"], + ["指令名稱", {"key": "value"}], + ["指令名稱", ["arg1", "arg2"]] + ] +} +``` + +- 使用 **dict** `{}` 作為第二個元素傳遞關鍵字參數(`**kwargs`) +- 使用 **list** `[]` 作為第二個元素傳遞位置參數(`*args`) +- 只寫指令名稱(不含第二個元素)表示無參數指令 + +### 可用的腳本指令 + +| 指令 | 說明 | 參數 | +|------|------|------| +| `MT_smtp_later_init` | 初始化並登入 SMTP | 無 | +| `MT_smtp_create_message_and_send` | 建立並寄送郵件 | `{"message_content": str, "message_setting_dict": dict}` | +| `MT_smtp_create_message_with_attach_and_send` | 建立並寄送帶附件的郵件 | `{"message_content": str, "message_setting_dict": dict, "attach_file": str, "use_html": bool}` | +| `smtp_quit` | 中斷 SMTP 連線 | 無 | +| `MT_imap_later_init` | 初始化並登入 IMAP | 無 | +| `MT_imap_select_mailbox` | 選擇信箱 | `{"mailbox": str, "readonly": bool}`(預設:INBOX)| +| `MT_imap_search_mailbox` | 搜尋並取得郵件詳細資訊 | `{"search_str": str, "charset": str}` | +| `MT_imap_mail_content_list` | 取得所有郵件內容列表 | `{"search_str": str, "charset": str}` | +| `MT_imap_output_all_mail_as_file` | 匯出所有郵件為檔案 | `{"search_str": str, "charset": str}` | +| `MT_imap_quit` | 中斷 IMAP 連線 | 無 | +| `MT_set_mail_thunder_os_environ` | 設定驗證環境變數 | `{"mail_thunder_user": str, "mail_thunder_user_password": str}` | +| `MT_get_mail_thunder_os_environ` | 取得驗證環境變數 | 無 | +| `MT_add_package_to_executor` | 載入 Python 套件至執行器 | `["套件名稱"]` | + +**範例 — 透過 JSON 腳本寄送郵件:** + +```json +{ + "auto_control": [ + ["MT_smtp_later_init"], + ["MT_smtp_create_message_and_send", { + "message_content": "Hello World!", + "message_setting_dict": { + "Subject": "自動化郵件", + "To": "receiver@gmail.com", + "From": "sender@gmail.com" + } + }], + ["smtp_quit"] + ] +} +``` + +**範例 — 讀取並匯出所有郵件:** + +```json +{ + "auto_control": [ + ["MT_imap_later_init"], + ["MT_imap_select_mailbox"], + ["MT_imap_output_all_mail_as_file"] + ] +} +``` + +### 擴充自訂指令 + +你可以將自己的函式加入腳本執行器: + +```python +from je_mail_thunder import add_command_to_executor + +def my_custom_function(param1, param2): + print(f"自訂指令: {param1}, {param2}") + +add_command_to_executor({"my_command": my_custom_function}) +``` + +之後即可在 JSON 動作檔中使用 `"my_command"`。 + +### 動態載入套件 + +在執行時動態載入任何已安裝的 Python 套件至執行器: + +```json +{ + "auto_control": [ + ["MT_add_package_to_executor", ["os"]], + ["os_system", ["echo Hello from os.system"]] + ] +} +``` + +這會載入指定套件的所有函式、內建功能和類別,並以 `套件名稱_` 為前綴。 + +> **警告:** 將 `os` 等套件載入執行器可能存在安全風險。請僅載入可信任的套件並驗證所有輸入。 + +--- + +## 專案模板 + +MailThunder 可以快速建立包含預設模板的專案: + +```python +from je_mail_thunder import create_project_dir + +create_project_dir() # 在目前目錄建立 +# 或 +create_project_dir(project_path="/path/to/project", parent_name="MyMailProject") +``` + +建立的目錄結構如下: + +``` +MyMailProject/ + keyword/ + keyword1.json # SMTP 寄送郵件模板 + keyword2.json # IMAP 讀取並匯出模板 + bad_keyword_1.json # 套件載入範例(安全性警告) + executor/ + executor_one_file.py # 執行單一動作檔 + executor_folder.py # 執行目錄內所有動作檔 + executor_bad_file.py # 不良實踐範例 +``` + +--- + +## 命令列介面 + +MailThunder 透過 `python -m je_mail_thunder` 提供命令列介面: + +```bash +# 執行單一 JSON 動作檔 +python -m je_mail_thunder -e /path/to/action.json + +# 執行目錄內所有 JSON 動作檔 +python -m je_mail_thunder -d /path/to/actions/ + +# 直接執行 JSON 字串 +python -m je_mail_thunder --execute_str '[["MT_smtp_later_init"], ["smtp_quit"]]' + +# 建立包含模板的新專案 +python -m je_mail_thunder -c /path/to/project +``` + +| 旗標 | 完整旗標 | 說明 | +|------|----------|------| +| `-e` | `--execute_file` | 執行單一 JSON 動作檔 | +| `-d` | `--execute_dir` | 執行目錄內所有 JSON 動作檔 | +| `-c` | `--create_project` | 建立包含模板的專案 | +| | `--execute_str` | 直接執行 JSON 字串 | + +--- + +## Socket 伺服器 + +MailThunder 內建 TCP Socket 伺服器,可接收遠端 JSON 指令: + +```python +from je_mail_thunder.utils.socket_server.mail_thunder_socket_server import start_autocontrol_socket_server + +server = start_autocontrol_socket_server(host="localhost", port=9944) +# 伺服器現在在背景執行緒中運行 +``` + +**向伺服器傳送指令:** + +```python +import socket +import json + +client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +client.connect(("localhost", 9944)) + +# 傳送動作指令 +command = json.dumps([["MT_smtp_later_init"], ["smtp_quit"]]) +client.send(command.encode("utf-8")) + +# 接收回應 +response = client.recv(8192).decode("utf-8") +print(response) + +client.close() +``` + +傳送 `"quit_server"` 可關閉伺服器。 + +--- + +## API 參考 + +### SMTPWrapper + +繼承自 `smtplib.SMTP_SSL`。預設主機:`smtp.gmail.com`,預設埠號:`465`。 + +| 方法 | 說明 | +|------|------| +| `later_init()` | 使用設定檔或環境變數登入 | +| `create_message(message_content, message_setting_dict, **kwargs)` | 建立 `EmailMessage` 物件 | +| `create_message_with_attach(message_content, message_setting_dict, attach_file, use_html=False)` | 建立帶附件的 `MIMEMultipart` 訊息 | +| `create_message_and_send(message_content, message_setting_dict, **kwargs)` | 建立並立即寄送郵件 | +| `create_message_with_attach_and_send(message_content, message_setting_dict, attach_file, use_html=False)` | 建立並寄送帶附件的郵件 | +| `try_to_login_with_env_or_content()` | 嘗試從設定檔或環境變數登入,回傳 `bool` | +| `quit()` | 中斷連線並關閉 | + +**使用其他 SMTP 服務商:** + +```python +from je_mail_thunder import SMTPWrapper + +# 範例:Outlook +smtp = SMTPWrapper(host="smtp.office365.com", port=587) +``` + +### IMAPWrapper + +繼承自 `imaplib.IMAP4_SSL`。預設主機:`imap.gmail.com`。 + +| 方法 | 說明 | +|------|------| +| `later_init()` | 使用設定檔或環境變數登入 | +| `select_mailbox(mailbox="INBOX", readonly=False)` | 選擇信箱,回傳 `bool` | +| `search_mailbox(search_str="ALL", charset=None)` | 搜尋並回傳原始郵件詳細資訊列表 | +| `mail_content_list(search_str="ALL", charset=None)` | 回傳已解析的郵件內容字典列表 | +| `output_all_mail_as_file(search_str="ALL", charset=None)` | 以主旨為檔名匯出所有郵件 | +| `quit()` | 關閉信箱並登出 | + +**郵件內容字典格式:** + +```python +{ + "SUBJECT": "郵件主旨", + "FROM": "sender@example.com", + "TO": "receiver@example.com", + "BODY": "郵件內容..." +} +``` + +### Executor 函式 + +| 函式 | 說明 | +|------|------| +| `execute_action(action_list)` | 執行動作指令列表 | +| `execute_files(execute_files_list)` | 執行多個 JSON 動作檔 | +| `add_command_to_executor(command_dict)` | 將自訂函式加入執行器 | +| `read_action_json(file_path)` | 讀取 JSON 動作檔 | + +### 工具函式 + +| 函式 | 說明 | +|------|------| +| `create_project_dir(project_path, parent_name)` | 建立包含模板的專案 | +| `set_mail_thunder_os_environ(user, password)` | 設定驗證環境變數 | +| `get_mail_thunder_os_environ()` | 取得驗證環境變數 | +| `read_output_content()` | 從目前工作目錄讀取 `mail_thunder_content.json` | +| `write_output_content()` | 將內容資料寫入 `mail_thunder_content.json` | +| `get_dir_files_as_list(path)` | 取得目錄內所有檔案列表 | + +--- + +## 專案結構 + +``` +MailThunder/ + je_mail_thunder/ + __init__.py # 公開 API 匯出 + __main__.py # CLI 進入點 + smtp/ + smtp_wrapper.py # SMTPWrapper 類別 + imap/ + imap_wrapper.py # IMAPWrapper 類別 + utils/ + exception/ # 自訂例外與錯誤標籤 + executor/ # JSON 腳本引擎 + file_process/ # 檔案工具函式 + json/ # JSON 檔案讀寫 + json_format/ # JSON 格式化 + logging/ # 日誌實例 + package_manager/ # 動態套件載入器 + project/ # 專案模板建立 + save_mail_user_content/ # 驗證設定與環境變數處理 + socket_server/ # TCP Socket 伺服器 + test/ # 單元測試 + docs/ # Sphinx 文件 +``` + +--- + +## 授權條款 + +本專案採用 [MIT 授權條款](../LICENSE)。 + +Copyright (c) 2021 JE-Chen