0x42
Форумчанин
- Регистрация
- 05.05.2025
- Сообщения
- 59
- Реакции
- 6
Вот интересный скрипт на питоне, который может отправлять письма по базе, база в текстовом виде, каждая строка - это email-адрес.
Пример базы:
Сам скрипт:
Шаблон письма letter.html должен находится в папке со скриптом.
Как пользоваться скриптом:
base_mail_to_send.txt - База емаил.
letter.html - Тело письма, должно находится в папке со скриптом.
Пример базы:
Сам скрипт:
Python:
#!/usr/bin/env python3
import re, sys, time, subprocess, pathlib, datetime, shutil
from email.message import EmailMessage
from email.headerregistry import Address
from email.header import Header
from email import policy
# ───── НАСТРОЙКИ ─────────────────────────────────────────────────────
SUBJECT_TXT = "Ваша тема"
FROM_ADDR = "Ваш обратный email"
FROM_NAME = "Oleg hostname"
HTML_PATH = pathlib.Path("letter.html")
PAUSE_SEC = 0.2
# ───── ПРЕДПРОВЕРКИ ──────────────────────────────────────────────────
def check_requirements():
ok = True
# sendmail
sendmail = shutil.which("sendmail") or "/usr/sbin/sendmail"
if not pathlib.Path(sendmail).is_file():
print("❌ sendmail не найден (ни /usr/sbin/sendmail, ни $PATH)")
ok = False
else:
print("✅ sendmail найден:", sendmail)
# письмо-шаблон
if not HTML_PATH.exists():
print(f"❌ HTML-шаблон {HTML_PATH} не найден")
ok = False
else:
print("✅ Шаблон письма:", HTML_PATH)
# From-адрес
if not re.match(r"^[^@]+@[^@]+\.[^@]+$", FROM_ADDR):
print("❌ FROM_ADDR невалидный:", FROM_ADDR)
ok = False
else:
print("✅ FROM:", FROM_ADDR)
# dig/dnsutils (опционально)
dig = shutil.which("dig")
if dig:
try:
spf = subprocess.getoutput(f'dig +short TXT {FROM_ADDR.split("@")[1]}')
dkim = subprocess.getoutput(f'dig +short TXT default._domainkey.{FROM_ADDR.split("@")[1]}')
dmarc = subprocess.getoutput(f'dig +short TXT _dmarc.{FROM_ADDR.split("@")[1]}')
print("📡 SPF :", "✅ найден" if "spf1" in spf else "⚠️ нет")
print("📡 DKIM :", "✅ найден" if "DKIM1" in dkim else "⚠️ нет")
print("📡 DMARC :", "✅ найден" if "DMARC1" in dmarc else "⚠️ нет")
except Exception:
print("⚠️ dig работает нестабильно")
else:
print("⚠️ dig не установлен — DNS-проверки пропущены")
if not ok:
sys.exit("🚫 Не выполнены минимальные условия, скрипт остановлен.")
check_requirements()
# ───── ЗАГРУЗКА СПИСКА ───────────────────────────────────────────────
SRC = (
pathlib.Path(sys.argv[1]).open("r", encoding="utf-8", errors="ignore")
if len(sys.argv) > 1 and sys.argv[1] != "-" else sys.stdin
)
# ───── ЛОГ ────────────────────────────────────────────────────────────
LOG_DIR = pathlib.Path("logs"); LOG_DIR.mkdir(exist_ok=True)
LOGFILE = LOG_DIR / f"mailer_{datetime.datetime.now():%F_%H-%M-%S}.log"
def log(txt="", end="\n"):
print(txt, end=end, flush=True)
LOGFILE.open("a", encoding="utf-8").write(txt + end)
log(f"\n========== {datetime.datetime.now():%F %T} START ==========")
# ───── ПОДГОТОВКА ПИСЬМА ──────────────────────────────────────────────
HTML_BODY = HTML_PATH.read_text(encoding="utf-8")
RE_MAIL = re.compile(r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}")
def make_msg(rcpt: str) -> bytes:
msg = EmailMessage(policy=policy.SMTP)
msg["From"] = Address(display_name=FROM_NAME, addr_spec=FROM_ADDR)
msg["To"] = rcpt
msg["Subject"] = str(Header(SUBJECT_TXT, "utf-8"))
msg.set_content("HTML-версия письма недоступна.", charset="utf-8")
msg.add_alternative(HTML_BODY, subtype="html", charset="utf-8")
msg["List-Unsubscribe"] = f"<https://osint42.org/unsubscribe?email={rcpt}>"
return msg.as_bytes()
def send(raw: bytes) -> bool:
return subprocess.run(
["/usr/sbin/sendmail", "-oi", "-t"],
input=raw,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
).returncode == 0
# ───── РАССЫЛКА ───────────────────────────────────────────────────────
total = ok = fail = 0
t0 = time.time()
for line in SRC:
m = RE_MAIL.search(line)
if not m:
continue
addr = m.group(0)
total += 1
log(f"[{total}] {addr} … ", end="")
if send(make_msg(addr)):
log("OK"); ok += 1
else:
log("FAIL"); fail += 1
time.sleep(PAUSE_SEC)
elapsed = time.time() - t0
log()
log(f"========== {datetime.datetime.now():%F %T} DONE ==========")
log(f"Success: {ok} Fail: {fail} Time: {elapsed:.1f}s")
Шаблон письма letter.html должен находится в папке со скриптом.
Как пользоваться скриптом:
Код:
chmod +x mail_bulk.py
./mail_bulk.py base_mail_to_send.txt
base_mail_to_send.txt - База емаил.
letter.html - Тело письма, должно находится в папке со скриптом.