Заметка Скрипт отправки email адресов по базе

  • Автор темы Автор темы 0x42
  • Дата начала Дата начала

0x42

Форумчанин
Регистрация
05.05.2025
Сообщения
59
Реакции
6
Вот интересный скрипт на питоне, который может отправлять письма по базе, база в текстовом виде, каждая строка - это email-адрес.

Пример базы:

Код:

Сам скрипт:
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 - Тело письма, должно находится в папке со скриптом.
 

Похожие темы

Назад
Верх Низ