I think now it works
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					config.json
 | 
				
			||||||
							
								
								
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					MIT License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2024 earthjasonlin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					SOFTWARE.
 | 
				
			||||||
							
								
								
									
										113
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,113 @@
 | 
				
			|||||||
 | 
					# MailForwarder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**此README由 ChatGPT-4o 生成**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					这个项目是一个邮件自动转发器,能够从指定的邮箱中读取未读邮件,并将其自动转发到配置文件中指定的收件人邮箱中。该项目支持使用代理服务器进行连接,并且可以处理包含附件的邮件。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 功能特性
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- 自动转发未读邮件
 | 
				
			||||||
 | 
					- 支持 HTML 和纯文本格式的邮件内容
 | 
				
			||||||
 | 
					- 支持邮件附件的转发
 | 
				
			||||||
 | 
					- 支持通过 SOCKS5 代理进行连接
 | 
				
			||||||
 | 
					- 支持多账户配置
 | 
				
			||||||
 | 
					- 可配置的检查间隔
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 安装与配置
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 环境要求
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Python 3.6+
 | 
				
			||||||
 | 
					- 需要安装以下 Python 库:
 | 
				
			||||||
 | 
					  - json
 | 
				
			||||||
 | 
					  - imaplib
 | 
				
			||||||
 | 
					  - smtplib
 | 
				
			||||||
 | 
					  - email
 | 
				
			||||||
 | 
					  - socks
 | 
				
			||||||
 | 
					  - logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 安装依赖
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					pip install pysocks
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 配置文件
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					请在项目根目录下创建一个名为 `config.json` 的配置文件,并根据以下格式进行配置(见`config-example.json`):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```json
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "check_interval": 60,
 | 
				
			||||||
 | 
					  "accounts": [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "email": "your_email@example.com",
 | 
				
			||||||
 | 
					      "password": "your_password",
 | 
				
			||||||
 | 
					      "enabled": true,
 | 
				
			||||||
 | 
					      "imap": {
 | 
				
			||||||
 | 
					        "server": "imap.example.com",
 | 
				
			||||||
 | 
					        "port": 993,
 | 
				
			||||||
 | 
					        "use_ssl": true
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "smtp": {
 | 
				
			||||||
 | 
					        "server": "smtp.example.com",
 | 
				
			||||||
 | 
					        "port": 587,
 | 
				
			||||||
 | 
					        "use_ssl": false,
 | 
				
			||||||
 | 
					        "use_starttls": true
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "forward": {
 | 
				
			||||||
 | 
					        "to": ["forward_to@example.com"]
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "proxy": {
 | 
				
			||||||
 | 
					        "enabled": false,
 | 
				
			||||||
 | 
					        "server": "proxy.example.com",
 | 
				
			||||||
 | 
					        "port": 1080
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 配置项说明
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `check_interval`: 检查邮件的时间间隔,单位为秒。
 | 
				
			||||||
 | 
					- `accounts`: 配置多个邮箱账户。
 | 
				
			||||||
 | 
					  - `email`: 邮箱地址。
 | 
				
			||||||
 | 
					  - `password`: 邮箱密码。
 | 
				
			||||||
 | 
					  - `enabled`: 是否启用该账户。
 | 
				
			||||||
 | 
					  - `imap`: IMAP 服务器配置。
 | 
				
			||||||
 | 
					    - `server`: IMAP 服务器地址。
 | 
				
			||||||
 | 
					    - `port`: IMAP 服务器端口。
 | 
				
			||||||
 | 
					    - `use_ssl`: 是否使用 SSL 连接。
 | 
				
			||||||
 | 
					  - `smtp`: SMTP 服务器配置。
 | 
				
			||||||
 | 
					    - `server`: SMTP 服务器地址。
 | 
				
			||||||
 | 
					    - `port`: SMTP 服务器端口。
 | 
				
			||||||
 | 
					    - `use_ssl`: 是否使用 SSL 连接。
 | 
				
			||||||
 | 
					    - `use_starttls`: 是否使用 STARTTLS 加密。
 | 
				
			||||||
 | 
					  - `forward`: 转发配置。
 | 
				
			||||||
 | 
					    - `to`: 转发邮件的收件人地址列表。
 | 
				
			||||||
 | 
					  - `proxy`: 代理服务器配置。
 | 
				
			||||||
 | 
					    - `enabled`: 是否启用代理。
 | 
				
			||||||
 | 
					    - `server`: 代理服务器地址。
 | 
				
			||||||
 | 
					    - `port`: 代理服务器端口。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 使用说明
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. 确保已经安装了所有依赖项,并正确配置了 `config.json` 文件。
 | 
				
			||||||
 | 
					2. 运行脚本:
 | 
				
			||||||
 | 
					   ```sh
 | 
				
			||||||
 | 
					   python main.py
 | 
				
			||||||
 | 
					   ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 日志
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					该脚本会在控制台输出日志信息,记录程序的运行状态、邮件处理情况以及错误信息。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 注意事项
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- 请确保配置文件中的邮箱账号和密码正确无误,并且邮箱服务支持 IMAP 和 SMTP 协议。
 | 
				
			||||||
 | 
					- 转发的邮件会包含一个自定义的头部和尾部,以提示收件人该邮件是自动转发的邮件。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 许可证
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					本项目遵循 MIT 许可证。详细信息请参见 LICENSE 文件。
 | 
				
			||||||
							
								
								
									
										53
									
								
								config-example.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								config-example.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "accounts": [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "enabled": false,
 | 
				
			||||||
 | 
					            "email": "sample@example.com",
 | 
				
			||||||
 | 
					            "password": "password",
 | 
				
			||||||
 | 
					            "imap": {
 | 
				
			||||||
 | 
					                "server": "imap.example.com",
 | 
				
			||||||
 | 
					                "port": 993,
 | 
				
			||||||
 | 
					                "use_ssl": true
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "smtp": {
 | 
				
			||||||
 | 
					                "server": "smtp.example.com",
 | 
				
			||||||
 | 
					                "port": 465,
 | 
				
			||||||
 | 
					                "use_ssl": true,
 | 
				
			||||||
 | 
					                "use_starttls": false
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "proxy": {
 | 
				
			||||||
 | 
					                "enabled": true,
 | 
				
			||||||
 | 
					                "server": "127.0.0.1",
 | 
				
			||||||
 | 
					                "port": 7897
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "forward": {
 | 
				
			||||||
 | 
					                "to": ["forward@example.com", "forward2@example.com"]
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "enabled": true,
 | 
				
			||||||
 | 
					            "email": "active@example.com",
 | 
				
			||||||
 | 
					            "password": "password",
 | 
				
			||||||
 | 
					            "imap": {
 | 
				
			||||||
 | 
					                "server": "imap.active.com",
 | 
				
			||||||
 | 
					                "port": 993,
 | 
				
			||||||
 | 
					                "use_ssl": true
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "smtp": {
 | 
				
			||||||
 | 
					                "server": "smtp.active.com",
 | 
				
			||||||
 | 
					                "port": 465,
 | 
				
			||||||
 | 
					                "use_ssl": false,
 | 
				
			||||||
 | 
					                "use_starttls": true
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "proxy": {
 | 
				
			||||||
 | 
					                "enabled": false,
 | 
				
			||||||
 | 
					                "server": "127.0.0.1",
 | 
				
			||||||
 | 
					                "port": 7897
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "forward": {
 | 
				
			||||||
 | 
					                "to": ["forward@example.com"]
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "check_interval": 10
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										152
									
								
								maincopy.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								maincopy.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,152 @@
 | 
				
			|||||||
 | 
					import json
 | 
				
			||||||
 | 
					import imaplib
 | 
				
			||||||
 | 
					import smtplib
 | 
				
			||||||
 | 
					import email
 | 
				
			||||||
 | 
					from email.mime.multipart import MIMEMultipart
 | 
				
			||||||
 | 
					from email.mime.text import MIMEText
 | 
				
			||||||
 | 
					import time
 | 
				
			||||||
 | 
					import logging
 | 
				
			||||||
 | 
					import socks
 | 
				
			||||||
 | 
					import socket
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from email.header import decode_header
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def decode_mime_words(s):
 | 
				
			||||||
 | 
					    decoded_fragments = decode_header(s)
 | 
				
			||||||
 | 
					    return ''.join(
 | 
				
			||||||
 | 
					        str(fragment, encoding or 'utf-8') if isinstance(fragment, bytes) else fragment
 | 
				
			||||||
 | 
					        for fragment, encoding in decoded_fragments
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def add_mask(original_msg, content):
 | 
				
			||||||
 | 
					    original_subject = decode_mime_words(original_msg['Subject'])
 | 
				
			||||||
 | 
					    header = f"""<table align=center style="background:#3d3d3d;padding:8px 16px;margin-top:30px;margin-bottom:30px;width:96%;border-radius:6px;max-width:1200px"width=100% bgcolor=#3D3D3D id=relay-email-header><tr><td style=font-size:xx-large;font-weight:bolder;color:#fff width=50% align=left>Forwarded Email<td style=color:#fff;text-align:right width=50% align=right><p>From: {original_msg['From']}<p>To: {original_msg['To']}<p>Subject: {original_subject}</table><table align=center style=padding:0;max-width:850px width=100%><tr><td style=padding-left:15px;padding-right:15px width=100%>"""
 | 
				
			||||||
 | 
					    footer = f"""<table align=center bgcolor=#3D3D3D style="background:#3d3d3d;padding:8px 16px;margin-top:30px;margin-bottom:30px;width:96%;border-radius:6px;max-width:1200px"width=100%><tr><td align=left style=color:#d22;font-size:xx-large;font-weight:bolder width=50%>FORWARDED<td align=right style=color:#fff;text-align:left width=50%><p style=font-size:x-large;font-weight:700;margin-block:0>Notice:<p style=margin-block:.1em> This is a automatically forwarded email, which means it may contains something bad.<p style=margin-block:.1em> You shouldn't reply directly to this email, it will never reach your destination!</table>"""
 | 
				
			||||||
 | 
					    return header + content + footer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def load_config(config_file='config.json'):
 | 
				
			||||||
 | 
					    with open(config_file, 'r') as file:
 | 
				
			||||||
 | 
					        config = json.load(file)
 | 
				
			||||||
 | 
					    return config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def set_proxy(proxy_config):
 | 
				
			||||||
 | 
					    socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, proxy_config['server'], proxy_config['port'])
 | 
				
			||||||
 | 
					    socket.socket = socks.socksocket
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def setup_logging():
 | 
				
			||||||
 | 
					    logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
 | 
				
			||||||
 | 
					    logger = logging.getLogger()
 | 
				
			||||||
 | 
					    return logger
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_unforwarded_emails(account_config, logger):
 | 
				
			||||||
 | 
					    if account_config['proxy']['enabled']:
 | 
				
			||||||
 | 
					        set_proxy(account_config['proxy'])
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if account_config['imap'].get('use_ssl', True):
 | 
				
			||||||
 | 
					        imap = imaplib.IMAP4_SSL(account_config['imap']['server'], account_config['imap']['port'])
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        imap = imaplib.IMAP4(account_config['imap']['server'], account_config['imap']['port'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    imap.login(account_config['email'], account_config['password'])
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if "163.com" in account_config['email'] or "126.com" in account_config['email']:
 | 
				
			||||||
 | 
					        imaplib.Commands['ID'] = ('AUTH')
 | 
				
			||||||
 | 
					        args = ("name","XXXX","contact","XXXX@163.com","version","1.0.0","vendor","myclient")
 | 
				
			||||||
 | 
					        typ, dat = imap._simple_command('ID', '("' + '" "'.join(args) + '")')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    imap.select()
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    status, messages = imap.search(None, 'UNSEEN')
 | 
				
			||||||
 | 
					    email_ids = messages[0].split()
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    emails = []
 | 
				
			||||||
 | 
					    for email_id in email_ids:
 | 
				
			||||||
 | 
					        status, data = imap.fetch(email_id, '(RFC822)')
 | 
				
			||||||
 | 
					        for response_part in data:
 | 
				
			||||||
 | 
					            if isinstance(response_part, tuple):
 | 
				
			||||||
 | 
					                msg = email.message_from_bytes(response_part[1])
 | 
				
			||||||
 | 
					                if 'Forwarded' not in msg['Subject']:
 | 
				
			||||||
 | 
					                    emails.append((email_id, msg))
 | 
				
			||||||
 | 
					    imap.logout()
 | 
				
			||||||
 | 
					    logger.info(f"Retrieved {len(emails)} new emails from {account_config['email']}")
 | 
				
			||||||
 | 
					    return emails
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def forward_emails(account_config, emails, logger):
 | 
				
			||||||
 | 
					    if account_config['proxy']['enabled']:
 | 
				
			||||||
 | 
					        set_proxy(account_config['proxy'])
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    smtp = None
 | 
				
			||||||
 | 
					    if account_config['smtp'].get('use_ssl', False):
 | 
				
			||||||
 | 
					        smtp = smtplib.SMTP_SSL(account_config['smtp']['server'], account_config['smtp']['port'])
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        smtp = smtplib.SMTP(account_config['smtp']['server'], account_config['smtp']['port'])
 | 
				
			||||||
 | 
					        if account_config['smtp'].get('use_starttls', False):
 | 
				
			||||||
 | 
					            smtp.starttls()
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    smtp.login(account_config['email'], account_config['password'])
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    for email_id, original_msg in emails:
 | 
				
			||||||
 | 
					        for recipient in account_config['forward']['to']:
 | 
				
			||||||
 | 
					            msg = MIMEMultipart('mixed')
 | 
				
			||||||
 | 
					            msg['From'] = account_config['email']
 | 
				
			||||||
 | 
					            msg['To'] = recipient
 | 
				
			||||||
 | 
					            original_subject = decode_mime_words(original_msg['Subject'])
 | 
				
			||||||
 | 
					            msg['Subject'] = original_subject
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            body = ""
 | 
				
			||||||
 | 
					            attachments = []
 | 
				
			||||||
 | 
					            if original_msg.is_multipart():
 | 
				
			||||||
 | 
					                for part in original_msg.walk():
 | 
				
			||||||
 | 
					                    content_type = part.get_content_type()
 | 
				
			||||||
 | 
					                    content_disposition = str(part.get("Content-Disposition"))
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    if "attachment" in content_disposition or part.get_filename():
 | 
				
			||||||
 | 
					                        attachments.append(part)
 | 
				
			||||||
 | 
					                    elif content_type == 'text/html':
 | 
				
			||||||
 | 
					                        body = part.get_payload(decode=True).decode()
 | 
				
			||||||
 | 
					                    elif content_type == 'text/plain' and not body:
 | 
				
			||||||
 | 
					                        body = part.get_payload(decode=True).decode()
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                body = original_msg.get_payload(decode=True).decode()
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if not body:
 | 
				
			||||||
 | 
					                logger.error(f"Failed to extract body from email {email_id}")
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            html_content = add_mask(original_msg, body)
 | 
				
			||||||
 | 
					            msg.attach(MIMEText(html_content, 'html'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for attachment in attachments:
 | 
				
			||||||
 | 
					                filename = attachment.get_filename()
 | 
				
			||||||
 | 
					                if decode_header(filename):
 | 
				
			||||||
 | 
					                    filename = decode_mime_words(filename)
 | 
				
			||||||
 | 
					                attachment.add_header('Content-Disposition', 'attachment', filename=filename)
 | 
				
			||||||
 | 
					                msg.attach(attachment)
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            smtp.sendmail(account_config['email'], recipient, msg.as_string())
 | 
				
			||||||
 | 
					            logger.info(f"Forwarded email {original_subject} to {recipient}")
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    smtp.quit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def main():
 | 
				
			||||||
 | 
					    logger = setup_logging()
 | 
				
			||||||
 | 
					    config = load_config()
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    while True:
 | 
				
			||||||
 | 
					        for account in config['accounts']:
 | 
				
			||||||
 | 
					            if account['enabled']:
 | 
				
			||||||
 | 
					                try:
 | 
				
			||||||
 | 
					                    emails = get_unforwarded_emails(account, logger)
 | 
				
			||||||
 | 
					                    if emails:
 | 
				
			||||||
 | 
					                        forward_emails(account, emails, logger)
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        logger.info(f"No new emails to forward for {account['email']}.")
 | 
				
			||||||
 | 
					                except Exception as e:
 | 
				
			||||||
 | 
					                    logger.error(f"Error processing account {account['email']}: {str(e)}")
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                logger.info(f"Account {account['email']} is disabled.")
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        time.sleep(config.get('check_interval', 60))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					    main()
 | 
				
			||||||
							
								
								
									
										72
									
								
								template.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								template.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					<table
 | 
				
			||||||
 | 
					    id="relay-email-header"
 | 
				
			||||||
 | 
					    style="
 | 
				
			||||||
 | 
					        background: #3d3d3d;
 | 
				
			||||||
 | 
					        padding: 8px 16px;
 | 
				
			||||||
 | 
					        margin-top: 30px;
 | 
				
			||||||
 | 
					        margin-bottom: 30px;
 | 
				
			||||||
 | 
					        width: 96%;
 | 
				
			||||||
 | 
					        border-radius: 6px;
 | 
				
			||||||
 | 
					        max-width: 1200px;
 | 
				
			||||||
 | 
					    "
 | 
				
			||||||
 | 
					    width="100%"
 | 
				
			||||||
 | 
					    bgcolor="#3D3D3D"
 | 
				
			||||||
 | 
					    align="center">
 | 
				
			||||||
 | 
					    <tbody>
 | 
				
			||||||
 | 
					        <tr>
 | 
				
			||||||
 | 
					            <td
 | 
				
			||||||
 | 
					                width="50%"
 | 
				
			||||||
 | 
					                align="left"
 | 
				
			||||||
 | 
					                style="
 | 
				
			||||||
 | 
					                    font-size: xx-large;
 | 
				
			||||||
 | 
					                    font-weight: bolder;
 | 
				
			||||||
 | 
					                    color: #ffffff;
 | 
				
			||||||
 | 
					                ">
 | 
				
			||||||
 | 
					                Forwarded Email
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					            <td width="50%" align="right" style="color: #ffffff; text-align: right;">
 | 
				
			||||||
 | 
					                <p>From: {original_msg['From']}</p>
 | 
				
			||||||
 | 
					                <p>To: {original_msg['To']}</p>
 | 
				
			||||||
 | 
					                <p>Subject: {original_subject}</p>
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					    </tbody>
 | 
				
			||||||
 | 
					</table>
 | 
				
			||||||
 | 
					<table style="padding: 0; max-width: 850px" width="100%" align="center">
 | 
				
			||||||
 | 
					    <tbody>
 | 
				
			||||||
 | 
					        <tr>
 | 
				
			||||||
 | 
					            <td style="padding-left: 15px; padding-right: 15px" width="100%">
 | 
				
			||||||
 | 
					                <!-- content -->
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					    </tbody>
 | 
				
			||||||
 | 
					</table>
 | 
				
			||||||
 | 
					<table
 | 
				
			||||||
 | 
					    style="
 | 
				
			||||||
 | 
					        background: #3d3d3d;
 | 
				
			||||||
 | 
					        padding: 8px 16px;
 | 
				
			||||||
 | 
					        margin-top: 30px;
 | 
				
			||||||
 | 
					        margin-bottom: 30px;
 | 
				
			||||||
 | 
					        width: 96%;
 | 
				
			||||||
 | 
					        border-radius: 6px;
 | 
				
			||||||
 | 
					        max-width: 1200px;
 | 
				
			||||||
 | 
					    "
 | 
				
			||||||
 | 
					    width="100%"
 | 
				
			||||||
 | 
					    bgcolor="#3D3D3D"
 | 
				
			||||||
 | 
					    align="center">
 | 
				
			||||||
 | 
					    <tbody>
 | 
				
			||||||
 | 
					        <tr>
 | 
				
			||||||
 | 
					            <td
 | 
				
			||||||
 | 
					                width="50%"
 | 
				
			||||||
 | 
					                align="left"
 | 
				
			||||||
 | 
					                style="color: #dd2222; font-size: xx-large; font-weight: bolder">
 | 
				
			||||||
 | 
					                FORWARDED
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					            <td width="50%" align="right" style="color: #ffffff; text-align: left;">
 | 
				
			||||||
 | 
					                <p style="font-size: x-large; font-weight: bold; margin-block: 0;">Notice:</p>
 | 
				
			||||||
 | 
					                <p style="margin-block: 0.1em;"> This is a automatically forwarded email, which means it may contains something bad.</p>
 | 
				
			||||||
 | 
					                <p style="margin-block: 0.1em;"> You shouldn't reply directly to this email, it will never reach your destination!</p>
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					    </tbody>
 | 
				
			||||||
 | 
					</table>
 | 
				
			||||||
		Reference in New Issue
	
	Block a user