🚀 Initial commit: Mutt Email-to-AI Pipeline

This commit is contained in:
MatrixHasYou 2026-04-29 11:05:22 +04:00
commit e48d05eac3
9 changed files with 2183 additions and 0 deletions

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
*.pdf
*.log
.export_progress
.phase2_progress
exported_emails/

74
.muttrc Normal file
View file

@ -0,0 +1,74 @@
# Mutt configuration for Gmail
# Простая совместимая версия
# === Личные данные ===
set realname = "MatrixHasYou"
set from = "ktybdsq@gmail.com"
set use_from = yes
# === IMAP (получение почты) ===
set imap_user = "ktybdsq@gmail.com"
set imap_pass = "hrur gguo srtm jpue"
set folder = "imaps://imap.gmail.com/"
set spoolfile = "+INBOX"
set mailbox = "+INBOX"
# === SMTP (отправка почты) ===
set smtp_url = "smtps://your.email@gmail.com@smtp.gmail.com:465"
set smtp_pass = "YOUR_APP_PASSWORD"
# === Настройки ящика ===
set mail_check = 60
set timeout = 60
set sort = threads
set sort_aux = last-date-received
# === Кодировки ===
set charset = utf-8
set send_charset = "us-ascii:utf-8"
# === Кэш ===
set header_cache = "~/.cache/mutt/headers"
set message_cachedir = "~/.cache/mutt/bodies"
set certificate_file = "~/.cache/mutt/certificates"
# === Просмотр ===
set pager_index_lines = 15
set menu_scroll = yes
set mark_old = no
set forward_decode = yes
set include = yes
set forward_format = "Fwd: %s"
# === Цвета (базовые) ===
color indicator white blue
color status white blue
color error red blue
color tilde blue
color attachment brightgreen black
color search brightyellow blue
color header cyan blue
color quoted cyan blue
color signature cyan blue
color tree red blue
color normal white blue
color message cyan blue
color deletion red blue
color flag cyan blue
color tag yellow blue
# === Индекс ===
color index red blue "~N"
color index green blue "~O"
color index cyan blue "~Z"
color index yellow blue "~F"
# === Алиасы ===
source ~/.mutt/aliases
# === Макросы ===
macro index,pager G "<change-folder>[Gmail]/All Mail<enter>" "Go to Gmail All Mail"
macro index,pager S "<change-folder>[Gmail]/Sent Mail<enter>" "Go to Sent"
macro index,pager D "<change-folder>[Gmail]/Drafts<enter>" "Go to Drafts"
macro index,pager T "<change-folder>[Gmail]/Trash<enter>" "Go to Trash"
macro index,pager A "<change-folder>[Gmail]/Spam<enter>" "Go to Spam"

227
analyze_emails.py Normal file
View file

@ -0,0 +1,227 @@
#!/usr/bin/env python3
"""
Анализ экспортированных писем.
Извлекает метаданные из PDF файлов и создаёт таблицу переписки.
"""
import os
import re
import json
from pathlib import Path
from datetime import datetime
import fitz # PyMuPDF
BASE_OUTPUT = Path("/home/matrixhasyou/mutt/exported_emails")
ALL_FOLDER = BASE_OUTPUT / "all"
# Папки с ответами (органы которым писали)
REPLY_FOLDERS = {
"gosuslugi.ru": "Госуслуги",
"gov.ru": "Правительство РФ",
"mailop.ru": "Почта России (mailop)",
"mvd.ru": "МВД России",
"rospotrebnadzor.ru": "Роспотребнадзор",
"russianpost.ru": "Почта России",
"ulgkh.ru": "УЛГКХ (Ульяновск)",
"ulgss.ru": "УЛГСС (Ульяновск)",
}
def parse_pdf_metadata(filepath):
"""Извлечь текст и метаданные из PDF."""
try:
doc = fitz.open(filepath)
text = ""
for page_num in range(min(3, len(doc))): # Первые 3 страницы
text += doc[page_num].get_text()
doc.close()
return text
except Exception as e:
return f"ERROR: {e}"
def extract_email_info(filename, text):
"""Извлечь информацию о письме из имени файла и текста."""
# Парсим имя файла: YYYY-MM-DD_sender_subject.pdf
parts = Path(filename).stem.split('_', 2)
if len(parts) >= 3:
date_str = parts[0]
sender = parts[1]
subject = parts[2]
else:
date_str = "unknown"
sender = "unknown"
subject = Path(filename).stem
# Анализируем текст на наличие признаков ответа
is_reply = False
reply_type = None # "formal" или "substantive"
text_lower = text.lower()
# Ключевые слова для определения типа ответа
formal_keywords = [
'ваше обращение', 'рассмотрено', 'сообщаем', 'уведомляем',
'в соответствии с', 'на основании', 'руководствуясь',
'отказано', 'не усматривается', 'не имеется оснований',
'в пределах компетенции', 'направляем в ваш адрес',
'информация предоставляется', 'согласно', 'в рамках',
'уважаемый', 'благодарим за обращение',
]
substantive_keywords = [
'удовлетворено', 'приняты меры', 'выявлены нарушения',
'обязать', 'устранить', 'проведена проверка',
'направлено предписание', 'штраф', 'предписани',
'срок устранения', 'контроль', 'исполнено',
'возбуждено дело', 'материалы переданы',
'установлено', 'подтверждено', 'выдано',
]
formal_count = sum(1 for kw in formal_keywords if kw in text_lower)
substantive_count = sum(1 for kw in substantive_keywords if kw in text_lower)
# Определяем тип
if formal_count > 0 or substantive_count > 0:
is_reply = True
if substantive_count > formal_count:
reply_type = "По существу ✓"
else:
reply_type = "Формальная отписка ⚠"
# Извлекаем номер входящего (если есть)
incoming_number = None
number_patterns = [
r'[№N]\s*[\.:]?\s*([A-Za-zА-Яа-я0-9\-\/]+)',
r'исх\.\s*[\.:]?\s*([A-Za-zА-Яа-я0-9\-\/]+)',
r'вх\.\s*[\.:]?\s*([A-Za-zА-Яа-я0-9\-\/]+)',
r'регистрационн\w*\s*[\.:]?\s*([A-Za-zА-Яа-я0-9\-\/]+)',
]
for pattern in number_patterns:
match = re.search(pattern, text[:2000], re.IGNORECASE)
if match:
incoming_number = match.group(1)
break
return {
'date': date_str,
'sender': sender,
'subject': subject[:60],
'is_reply': is_reply,
'reply_type': reply_type,
'incoming_number': incoming_number,
'formal_score': formal_count,
'substantive_score': substantive_count,
}
def analyze_all_emails():
"""Анализировать все письма и вернуть статистику."""
results = []
# Сканируем папки с ответами
for folder_name, folder_desc in REPLY_FOLDERS.items():
folder_path = BASE_OUTPUT / folder_name
if not folder_path.exists():
continue
pdf_files = sorted(folder_path.glob("*.pdf"))
for pdf_file in pdf_files:
text = parse_pdf_metadata(pdf_file)
info = extract_email_info(pdf_file.name, text)
info['folder'] = folder_desc
info['filename'] = pdf_file.name
results.append(info)
return results
def format_table(results):
"""Форматировать результаты в красивую таблицу для Telegram."""
# Сортируем по дате
results.sort(key=lambda x: x['date'])
# Заголовок
table = "📊 **ОТЧЁТ ПО ПЕРЕПИСКЕ С ОРГАНАМИ**\n"
table += f"📅 Дата формирования: {datetime.now().strftime('%d.%m.%Y')}\n"
table += "" * 50 + "\n\n"
# Группируем по папкам
by_folder = {}
for r in results:
folder = r['folder']
if folder not in by_folder:
by_folder[folder] = []
by_folder[folder].append(r)
total_sent = len(results)
total_replies = sum(1 for r in results if r['is_reply'])
total_formal = sum(1 for r in results if r['reply_type'] and 'Формальная' in r['reply_type'])
total_substantive = sum(1 for r in results if r['reply_type'] and 'существу' in r['reply_type'])
# Таблица по органам
table += "📮 **ПО ОРГАНАМ:**\n\n"
for folder, items in by_folder.items():
replies = sum(1 for i in items if i['is_reply'])
reply_pct = (replies / len(items) * 100) if items else 0
table += f"**{folder}**\n"
table += f"├─ Писем: {len(items)}\n"
table += f"├─ Ответов: {replies} ({reply_pct:.0f}%)\n"
# Последние 3 письма с деталями
recent = items[-3:] if len(items) > 3 else items
for idx, item in enumerate(recent):
num = len(items) - len(recent) + idx + 1
status = "✅ Ответ" if item['is_reply'] else "⏳ Нет ответа"
reply_detail = f"{item['reply_type']}" if item['reply_type'] else ""
incoming = f" [Вх.№ {item['incoming_number']}]" if item['incoming_number'] else ""
table += f"├─ #{num} | {item['date']} | {status}{reply_detail}{incoming}\n"
table += f"│ 📝 {item['subject'][:45]}...\n"
if len(items) > 3:
table += f"└─ ... и ещё {len(items) - 3} писем\n"
table += "\n"
# ИТОГО
table += "" * 50 + "\n"
table += "📈 **ИТОГО:**\n\n"
reply_pct_total = (total_replies / total_sent * 100) if total_sent else 0
formal_pct = (total_formal / total_replies * 100) if total_replies else 0
substantive_pct = (total_substantive / total_replies * 100) if total_replies else 0
table += f"✉️ Всего отправлено: **{total_sent}**\n"
table += f"✅ Получено ответов: **{total_replies}** ({reply_pct_total:.0f}%)\n"
table += f"⏳ Без ответа: **{total_sent - total_replies}**\n\n"
if total_replies > 0:
table += "📊 **КАЧЕСТВО ОТВЕТОВ:**\n\n"
table += f"⚠️ Формальные отписки: **{total_formal}** ({formal_pct:.0f}%)\n"
table += f"✅ Ответы по существу: **{total_substantive}** ({substantive_pct:.0f}%)\n\n"
table += "🎯 **ВЫВОД:**\n\n"
if substantive_pct > 50:
table += "Большинство ответов — **по существу**. Органы работают! 💪\n"
elif formal_pct > 70:
table += "Преобладают **формальные отписки**. Требуется escalation. ⚠️\n"
else:
table += "Смешанная картина. Нужно работать с каждым ответом отдельно.\n"
table += "\n" + "" * 50 + "\n"
table += f"🕐 Сформировано: {datetime.now().strftime('%H:%M %d.%m.%Y')}\n"
return table
if __name__ == '__main__':
print("Анализирую письма...")
results = analyze_all_emails()
print(f"Проанализировано {len(results)} писем\n")
table = format_table(results)
print(table)
# Сохраняем в файл
output_file = Path(__file__).parent / "report_table.txt"
output_file.write_text(table, encoding='utf-8')
print(f"\nОтчёт сохранён в {output_file}")

270
analyze_emails_detailed.py Normal file
View file

@ -0,0 +1,270 @@
#!/usr/bin/env python3
"""
Детальный анализ экспортированных писем полная таблица для Telegram.
"""
import os
import re
from pathlib import Path
from datetime import datetime
import fitz
BASE_OUTPUT = Path("/home/matrixhasyou/mutt/exported_emails")
REPLY_FOLDERS = {
"gosuslugi.ru": "🟦 Госуслуги",
"gov.ru": "🟪 Правительство РФ",
"mailop.ru": "🟨 Почта России (mailop)",
"mvd.ru": "🟥 МВД России",
"rospotrebnadzor.ru": "🟧 Роспотребнадзор",
"russianpost.ru": "📮 Почта России",
"ulgkh.ru": "🏢 УЛГКХ",
"ulgss.ru": "🏛 УЛГСС",
}
def parse_pdf_metadata(filepath):
"""Извлечь текст из PDF (первые 5 страниц)."""
try:
doc = fitz.open(filepath)
text = ""
for page_num in range(min(5, len(doc))):
text += doc[page_num].get_text()
doc.close()
return text
except Exception as e:
return f"ERROR: {e}"
def extract_incoming_number(text):
"""Извлечь номер входящего/исходящего."""
patterns = [
r'[№N]\s*[\.:]?\s*([A-Za-zА-Яа-я0-9\-\/\.]+)',
r'исх\.?\s*[\.:№\s]*\s*([A-Za-zА-Яа-я0-9\-\/\.]+)',
r'вх\.?\s*[\.:№\s]*\s*([A-Za-zА-Яа-я0-9\-\/\.]+)',
r'регистрации\s*[№:]\s*([A-Za-zА-Яа-я0-9\-\/\.]+)',
r'([0-9]{2,4}[-\/][A-Za-zА-я0-9]+[-\/][0-9]+)',
]
for pattern in patterns:
matches = re.finditer(pattern, text[:3000], re.IGNORECASE)
for match in matches:
val = match.group(1).strip()
# Фильтруем слишком короткие или мусорные значения
if len(val) > 3 and val.lower() not in ['reply', 'pdf', 'notification', 'fo']:
return val
return None
def extract_response_date(text):
"""Извлечь дату ответа."""
date_patterns = [
r'от\s+(\d{2}[\.\/]\d{2}[\.\/]\d{4})',
r'(\d{2}[\.\/]\d{2}[\.\/]\d{4})',
r'«(\d+)»\s+(\w+)\s+(\d{4})',
]
for pattern in date_patterns:
match = re.search(pattern, text[:2000])
if match:
return match.group(0)[:15]
return None
def classify_reply(text):
"""Определить тип ответа."""
text_lower = text.lower()
formal_markers = [
'ваше обращение рассмотрено', 'сообщаем вам', 'уведомляем',
'в соответствии с федеральным законом', 'в пределах компетенции',
'направляем в ваш адрес', 'в рамках действующего законодательства',
'уважаемый', 'благодарим за обращение', 'ваше предложение',
'разъясняем', 'доводим до вашего сведения',
'не усматривается оснований', 'не представляет возможным',
'в соответствии с положением', 'регулирующим',
'ваше предложение не подлежит', 'отказано',
]
substantive_markers = [
'удовлетворено', 'приняты меры', 'выявлены нарушения',
'обязать устранить', 'проведена проверка', 'выдано предписание',
'направлено предписание', 'привлечен к ответственности',
'возбуждено дело', 'штраф наложен', 'материалы переданы',
'установлено нарушение', 'признано незаконным',
'подлежит устранению', 'в срок до', 'контроль исполнения',
'исполнено в полном объеме', 'восстановлено',
'перерасчет', 'возмещено', 'компенсация',
]
formal_count = sum(1 for kw in formal_markers if kw in text_lower)
substantive_count = sum(1 for kw in substantive_markers if kw in text_lower)
if formal_count == 0 and substantive_count == 0:
# Проверяем есть ли вообще ответ
has_response_indicators = any(kw in text_lower for kw in [
'ответ', 'рассмотрение', 'сообщаем', 'уведомляем',
'уважаемый', 'обращение', 'письмо ваше'
])
if has_response_indicators:
return "Формальная ⚠️", formal_count, substantive_count
return None, 0, 0
if substantive_count > formal_count:
return "По существу ✅", formal_count, substantive_count
return "Формальная ⚠️", formal_count, substantive_count
def analyze_email(filepath):
"""Полный анализ одного письма."""
filename = filepath.name
# Парсим имя файла
parts = Path(filename).stem.split('_', 2)
if len(parts) >= 3:
date_str = parts[0]
sender = parts[1]
subject = parts[2]
else:
date_str = "unknown"
sender = "unknown"
subject = Path(filename).stem
# Анализируем текст
text = parse_pdf_metadata(filepath)
incoming_num = extract_incoming_number(text)
response_date = extract_response_date(text)
reply_type, formal_score, substantive_score = classify_reply(text)
is_sent = True # Это исходящее письмо
has_reply = reply_type is not None
return {
'date': date_str,
'sender': sender,
'subject': subject[:55],
'incoming_number': incoming_num,
'response_date': response_date,
'reply_type': reply_type,
'has_reply': has_reply,
'is_sent': is_sent,
'formal_score': formal_score,
'substantive_score': substantive_score,
}
def build_telegram_report():
"""Построить полный отчёт для Telegram."""
all_emails = []
# Сканируем все папки
for folder_name, folder_emoji in REPLY_FOLDERS.items():
folder_path = BASE_OUTPUT / folder_name
if not folder_path.exists():
continue
pdf_files = sorted(folder_path.glob("*.pdf"))
for pdf_file in pdf_files:
info = analyze_email(pdf_file)
info['folder_name'] = folder_name
info['folder_display'] = folder_emoji
all_emails.append(info)
# Сортируем по дате
all_emails.sort(key=lambda x: x['date'])
# Считаем статистику
total = len(all_emails)
with_replies = sum(1 for e in all_emails if e['has_reply'])
without_replies = total - with_replies
formal = sum(1 for e in all_emails if e['reply_type'] and 'Формальная' in str(e['reply_type']))
substantive = sum(1 for e in all_emails if e['reply_type'] and 'существу' in str(e['reply_type']))
# Строим отчёт
report = []
report.append("📊 **ПОЛНЫЙ ОТЧЁТ ПО ПЕРЕПИСКЕ С ОРГАНАМИ ВЛАСТИ**")
report.append(f"📅 Дата формирования: {datetime.now().strftime('%d.%m.%Y %H:%M')}")
report.append("" * 48)
report.append("")
# Группируем по органам
by_folder = {}
for email in all_emails:
folder = email['folder_display']
if folder not in by_folder:
by_folder[folder] = []
by_folder[folder].append(email)
# Для каждого органа
for folder_display, emails in by_folder.items():
report.append(f"{'' * 48}")
report.append(f"**{folder_display}**")
report.append(f"{'' * 48}")
report.append("")
replies_count = sum(1 for e in emails if e['has_reply'])
# Таблица писем
report.append(f"{'':<3}{'Дата':^10}{'Статус':^13}{'Вх. №':^18} │ Тема")
report.append(f"{'' * 3}─┼─{'' * 10}─┼─{'' * 13}─┼─{'' * 18}─┼─{'' * 30}")
for idx, email in enumerate(emails, 1):
status = ""
if email['has_reply']:
status = email['reply_type'][:13]
else:
status = "⏳ Нет ответа"
incoming = email['incoming_number'] or ""
if len(incoming) > 18:
incoming = incoming[:15] + "..."
subject = email['subject']
if len(subject) > 35:
subject = subject[:32] + "..."
report.append(f"{idx:<3}{email['date']:^10}{status:^13}{incoming:^18}{subject}")
report.append("")
report.append(f"📊 Итого по органу: {len(emails)} писем | Ответов: {replies_count} ({replies_count/len(emails)*100:.0f}%)")
report.append("")
# ИТОГО
report.append("=" * 48)
report.append("📈 **СВОДНАЯ СТАТИСТИКА**")
report.append("=" * 48)
report.append("")
report.append(f"✉️ **Всего отправлено писем:** {total}")
report.append(f"✅ **Получено ответов:** {with_replies} ({with_replies/total*100:.0f}%)")
report.append(f"⏳ **Без ответа:** {without_replies} ({without_replies/total*100:.0f}%)")
report.append("")
if with_replies > 0:
report.append("📊 **КАЧЕСТВО ОТВЕТОВ:**")
report.append(f" ⚠️ Формальные отписки: {formal} ({formal/with_replies*100:.0f}%)")
report.append(f" ✅ Ответы по существу: {substantive} ({substantive/with_replies*100:.0f}%)")
report.append("")
report.append("🎯 **ВЫВОД:**")
if substantive / with_replies > 0.5:
report.append(" Большинство ответов — по существу. Органы работают! 💪")
elif formal / with_replies > 0.7:
report.append(" ⚠️ Преобладают формальные отписки. Требуется:")
report.append(" • Повторные обращения с требованием ответа по существу")
report.append(" • Жалобы в вышестоящие органы")
report.append(" • Обращение в прокуратуру на бездействие")
else:
report.append(" Смешанная картина. Требуется работа с каждым ответом.")
report.append("")
report.append("=" * 48)
report.append(f"🕐 Отчёт сформирован: {datetime.now().strftime('%H:%M %d.%m.%Y')}")
report.append("=" * 48)
return "\n".join(report)
if __name__ == '__main__':
print("Формирую детальный отчёт...")
report = build_telegram_report()
print(report)
# Сохраняем
output_file = Path(__file__).parent / "report_detailed.txt"
output_file.write_text(report, encoding='utf-8')
print(f"\n\n📄 Отчёт сохранён: {output_file}")

86
consolidate_to_mega_pdf.py Executable file
View file

@ -0,0 +1,86 @@
#!/usr/bin/env python3
"""
Consolidates all individual email PDFs into one giant PDF for NotebookLM.
Sorted by date (prefix in filename).
"""
import os
import sys
import fitz # PyMuPDF
from pathlib import Path
import logging
import requests
from datetime import datetime
# === CONFIG ===
BASE_DIR = Path(__file__).parent
SOURCE_DIR = BASE_DIR / "exported_emails" / "all"
OUTPUT_FILE = BASE_DIR / "ALL_EMAILS_CONSOLIDATED.pdf"
BOT_TOKEN = "8725618164:AAH1tGalq-pw1l0t4P5c0sdLkCVJdh7IE7M"
CHAT_ID = "197957361"
PROXY = "socks5h://127.0.0.1:10808"
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
log = logging.getLogger("Consolidator")
def send_tg_alert(count, size_mb):
url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage"
text = f"""
🔥 <b>ВАЖНО: СВОДНЫЙ ФАЙЛ ПОЧТЫ ОБНОВЛЕН!</b> 🔥
📑 <b>Файл:</b> <code>ALL_EMAILS_CONSOLIDATED.pdf</code>
📧 <b>Всего писем в архиве:</b> {count}
🐘 <b>Размер файла:</b> {size_mb:.2f} МБ
📅 <b>Обновлено:</b> {datetime.now().strftime('%Y-%m-%d %H:%M')}
🚀 <b>СРОЧНО:</b> Загрузи этот файл в Google Drive и обнови источники в <b>NotebookLM</b>!
<i>Старые данные AI должен "забыть", новые осознать.</i>
"""
try:
requests.post(url, json={"chat_id": CHAT_ID, "text": text, "parse_mode": "HTML"},
proxies={"https": PROXY}, timeout=20)
log.info("✅ Telegram alert sent.")
except Exception as e:
log.error(f"❌ TG Alert failed: {e}")
def consolidate():
log.info("Starting consolidation...")
if not SOURCE_DIR.exists():
log.error(f"Source directory {SOURCE_DIR} not found!")
return
pdf_files = list(SOURCE_DIR.glob("*.pdf"))
if not pdf_files:
log.warning("No PDF files found to consolidate.")
return
# Sort by filename (which starts with date YYYY-MM-DD or contains it)
# Most files are: domain_YYYY-MM-DD_... or YYYY-MM-DD_...
# We'll just use natural sort of filenames.
pdf_files.sort(key=lambda x: x.name)
log.info(f"Found {len(pdf_files)} PDFs. Merging...")
merger = fitz.open()
for pdf_path in pdf_files:
try:
doc = fitz.open(pdf_path)
merger.insert_pdf(doc)
doc.close()
except Exception as e:
log.warning(f"Failed to add {pdf_path.name}: {e}")
if len(merger) > 0:
merger.save(OUTPUT_FILE, garbage=3, deflate=True)
size_mb = OUTPUT_FILE.stat().st_size / (1024 * 1024)
log.info(f"✅ Consolidated PDF saved: {OUTPUT_FILE} ({size_mb:.2f} MB)")
merger.close()
# Send alert
send_tg_alert(len(pdf_files), size_mb)
else:
log.error("Merger result is empty.")
merger.close()
if __name__ == "__main__":
consolidate()

577
export_emails.py Normal file
View file

@ -0,0 +1,577 @@
#!/usr/bin/env python3
"""
Gmail IMAP email exporter v3 optimized.
Single IMAP query for all emails since Dec 20, 2025, then filter by domains in Python.
Each email becomes a PDF with body + attachments merged.
Organized by domain and also in a flat 'all' folder.
"""
import os
import sys
import re
import time
import logging
from pathlib import Path
from datetime import datetime, date
from email.utils import parsedate_to_datetime
from imap_tools import MailBox, AND
from weasyprint import HTML
from fpdf import FPDF
import fitz # PyMuPDF
# === CONFIG ===
IMAP_SERVER = "imap.gmail.com"
# Извлекаем учётку из .muttrc (сначала в проекте, потом в home)
MUTT_CONF = Path(__file__).parent / ".muttrc"
if not MUTT_CONF.exists():
MUTT_CONF = Path.home() / ".muttrc"
# Domains to search
DOMAINS = [
"gosuslugi.ru", "dom.gosuslugi.ru", "gov.ru", "duma.gov.ru",
"mvd.gov.ru", "mvd.ru", "rkn.gov.ru", "nalog.gov.ru", "nalog.ru",
"genproc.gov.ru", "pfr.gov.ru", "fss.ru", "rospotrebnadzor.ru",
"russianpost.ru", "mailop.ru", "73.mailop.ru", "uk-service.ru",
"ulgss.ru", "ulgov.ru", "ulgkh.ru", "dgi.ru", "mos.ru", "pfrf.ru",
"fsin.gov.ru", "skrf.ru", "epp.genproc.gov.ru", "ugpr.ru",
"fas.gov.ru", "minstroyrf.gov.ru", "gkh.ru", "sudrf.ru",
]
# From this date
SINCE_DATE = date(2025, 12, 20)
# Gmail folder to search
GMAIL_FOLDER = "[Gmail]/Вся почта"
# Output
BASE_OUTPUT = Path(__file__).parent / "exported_emails"
ALL_FOLDER = BASE_OUTPUT / "all"
# Progress tracking
PROGRESS_FILE = Path(__file__).parent / ".export_progress"
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
handlers=[
logging.FileHandler(Path(__file__).parent / "export.log", encoding="utf-8"),
logging.StreamHandler(sys.stdout),
],
)
log = logging.getLogger(__name__)
def load_progress():
"""Load set of already processed UIDs."""
if PROGRESS_FILE.exists():
return set(PROGRESS_FILE.read_text().strip().splitlines())
return set()
def save_progress(uid, processed_set):
"""Save progress after each email."""
processed_set.add(str(uid))
PROGRESS_FILE.write_text("\n".join(processed_set))
def sanitize_filename(name, max_len=80):
"""Make filename safe."""
name = re.sub(r'[<>:"/\\|?*\x00-\x1f]', '_', name)
name = re.sub(r'\s+', ' ', name).strip()
return name[:max_len]
def parse_mutt_config():
"""Extract IMAP user and password from .muttrc."""
config = {}
with open(MUTT_CONF) as f:
for line in f:
line = line.strip()
if line.startswith('#') or not line:
continue
match = re.match(r'set\s+(\w+)\s*=\s*"([^"]*)"', line)
if not match:
match = re.match(r'set\s+(\w+)\s*=\s*(\S+)', line)
if match:
key, val = match.group(1), match.group(2)
config[key] = val
return config
def html_to_pdf_stream(html_content):
"""Convert HTML to PDF bytes using weasyprint, fallback to fpdf."""
try:
html_doc = HTML(string=html_content)
return html_doc.write_pdf()
except Exception as e:
log.warning(f"weasyprint failed, using fpdf fallback: {e}")
return html_to_pdf_fpdf(html_content)
def html_to_pdf_fpdf(html_content):
"""Fallback: strip HTML and use FPDF."""
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_content, 'lxml')
text = soup.get_text(separator='\n')
pdf = FPDF()
pdf.add_page()
pdf.add_font('DejaVu', '', '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', uni=True)
pdf.add_font('DejaVu', 'B', '/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf', uni=True)
pdf.set_font('DejaVu', '', 10)
lines = [line for line in text.split('\n') if line.strip()]
for line in lines:
pdf.multi_cell(0, 6, line)
pdf.ln(1)
return pdf.output()
def convert_attachment_to_pdf(attachment_data, filename, content_type):
"""Convert an attachment to PDF."""
ext = Path(filename).suffix.lower()
try:
if ext in ('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp', '.svg'):
pdf = FPDF()
pdf.add_page()
img_w, img_h = get_image_dims(attachment_data)
page_w = pdf.w - 20
scale = min(page_w / img_w, (pdf.h - 20) / img_h, 1.0)
w, h = img_w * scale, img_h * scale
import tempfile
with tempfile.NamedTemporaryFile(suffix=ext, delete=False) as tmp:
tmp.write(attachment_data)
tmp_path = tmp.name
try:
pdf.image(tmp_path, x=10, y=10, w=w, h=h)
finally:
os.unlink(tmp_path)
return pdf.output()
elif ext in ('.doc', '.docx'):
import tempfile, subprocess
with tempfile.TemporaryDirectory() as tmpdir:
src = Path(tmpdir) / filename
src.write_bytes(attachment_data)
subprocess.run(
['libreoffice', '--headless', '--convert-to', 'pdf',
'--outdir', tmpdir, str(src)],
capture_output=True, timeout=120
)
pdf_path = src.with_suffix('.pdf')
if pdf_path.exists():
return pdf_path.read_bytes()
elif ext == '.pdf':
return attachment_data
elif ext in ('.xls', '.xlsx'):
import tempfile, subprocess
with tempfile.TemporaryDirectory() as tmpdir:
src = Path(tmpdir) / filename
src.write_bytes(attachment_data)
subprocess.run(
['libreoffice', '--headless', '--convert-to', 'pdf',
'--outdir', tmpdir, str(src)],
capture_output=True, timeout=120
)
pdf_path = src.with_suffix('.pdf')
if pdf_path.exists():
return pdf_path.read_bytes()
elif ext in ('.txt', '.csv', '.log', '.xml', '.html', '.htm'):
try:
text = attachment_data.decode('utf-8', errors='replace')
except:
text = attachment_data.decode('latin-1', errors='replace')
return html_to_pdf_fpdf(text)
else:
info = f"Attachment: {filename}\nType: {content_type}\nSize: {len(attachment_data)} bytes\n\n[Binary content - not converted]"
return html_to_pdf_fpdf(info)
except Exception as e:
log.warning(f"Failed to convert {filename}: {e}")
info = f"Attachment: {filename}\nType: {content_type}\nSize: {len(attachment_data)} bytes\n\nConversion failed: {e}"
return html_to_pdf_fpdf(info)
def get_image_dims(data):
"""Get image dimensions."""
import io
from PIL import Image
img = Image.open(io.BytesIO(data))
w_px, h_px = img.size
w_mm = w_px * 25.4 / 96
h_mm = h_px * 25.4 / 96
return w_mm, h_mm
def merge_pdfs(pdf_bytes_list):
"""Merge multiple PDFs into one."""
if not pdf_bytes_list:
return None
if len(pdf_bytes_list) == 1:
return pdf_bytes_list[0]
merger = fitz.open()
for pdf_bytes in pdf_bytes_list:
try:
doc = fitz.open(stream=pdf_bytes, filetype="pdf")
merger.insert_pdf(doc)
except Exception as e:
log.warning(f"Failed to merge a PDF section: {e}")
output = merger.tobytes()
merger.close()
return output
def build_email_html(msg):
"""Build nice HTML representation of email with headers."""
subject = msg.subject or "(Без темы)"
from_addr = msg.from_ or "unknown"
to_addr = ", ".join(msg.to) if msg.to else "unknown"
cc_addr = ", ".join(msg.cc) if msg.cc else ""
date_str = msg.date_str or str(msg.date) if msg.date else "unknown"
body_html = msg.html
if not body_html and msg.text:
text = msg.text
text_escaped = text.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
body_html = text_escaped.replace('\n', '<br>\n')
elif not body_html:
body_html = "<p><i>(Нет тела письма)</i></p>"
attachments_info = ""
if msg.attachments:
att_items = []
for att in msg.attachments:
att_items.append(f'<li>{att.filename} ({att.content_type}, {att.size} bytes)</li>')
attachments_info = '<h3 style="color:#555;">Вложения:</h3><ul>' + ''.join(att_items) + '</ul>'
html = f"""
<html>
<head>
<meta charset="utf-8">
<style>
body {{ font-family: 'DejaVu Sans', Arial, sans-serif; font-size: 12px; margin: 20px; color: #333; }}
.header {{ background: #f0f4f8; padding: 15px; border-radius: 5px; margin-bottom: 15px; border-left: 4px solid #3b82f6; }}
.header h2 {{ margin: 0 0 10px 0; font-size: 16px; color: #1e40af; }}
.header table {{ width: 100%; }}
.header td {{ padding: 3px 5px; vertical-align: top; }}
.header td:first-child {{ font-weight: bold; width: 80px; color: #555; }}
.body {{ line-height: 1.6; }}
.attachments {{ margin-top: 20px; padding: 10px; background: #f9fafb; border-radius: 3px; }}
.attachments li {{ margin: 3px 0; color: #666; }}
</style>
</head>
<body>
<div class="header">
<h2>{subject}</h2>
<table>
<tr><td>От:</td><td>{from_addr}</td></tr>
<tr><td>Кому:</td><td>{to_addr}</td></tr>
{f'<tr><td>Копия:</td><td>{cc_addr}</td></tr>' if cc_addr else ''}
<tr><td>Дата:</td><td>{date_str}</td></tr>
</table>
</div>
<div class="body">
{body_html}
</div>
{f'<div class="attachments">{attachments_info}</div>' if attachments_info else ''}
</body>
</html>
"""
return html
def matches_domain(addr, domains):
"""Check if address matches any domain. Returns matched domain or None."""
if not addr:
return None
addr_lower = addr.lower()
for domain in domains:
if domain.lower() in addr_lower:
return domain
return None
def main():
log.info("=" * 60)
log.info("Gmail Email Exporter v3 — starting")
log.info("=" * 60)
# Parse config
config = parse_mutt_config()
imap_user = config.get('imap_user', '')
imap_pass = config.get('imap_pass', '')
if not imap_user or imap_user == 'your.email@gmail.com':
log.error("ERROR: Не настроены учётные данные в .muttrc!")
log.error("Укажите реальный imap_user и imap_pass (App Password)")
sys.exit(1)
log.info(f"IMAP User: {imap_user}")
log.info(f"Domains: {len(DOMAINS)} domains")
log.info(f"Since: {SINCE_DATE.strftime('%Y-%m-%d')}")
# Create output dirs
BASE_OUTPUT.mkdir(parents=True, exist_ok=True)
ALL_FOLDER.mkdir(parents=True, exist_ok=True)
# Load progress
processed = load_progress()
log.info(f"Previously processed: {len(processed)} emails")
# Connect
log.info("Connecting to Gmail IMAP...")
try:
mailbox = MailBox(IMAP_SERVER).login(imap_user, imap_pass, initial_folder=GMAIL_FOLDER)
log.info("Connected successfully!")
except Exception as e:
log.error(f"Failed to connect: {e}")
sys.exit(1)
# Phase 1: Fetch headers only to find matching emails
log.info("Phase 1: Scanning emails (headers only) to find matches...")
scan_start = time.time()
matching_uids = []
total_scanned = 0
last_log_time = time.time()
# Fetch headers only first — much faster
for msg in mailbox.fetch(
AND(date_gte=SINCE_DATE),
bulk=True,
headers_only=True,
mark_seen=False,
):
total_scanned += 1
# Log every 10 seconds
now = time.time()
if now - last_log_time > 10:
elapsed = now - scan_start
rate = total_scanned / elapsed if elapsed > 0 else 0
log.info(f" Scanned: {total_scanned} ({rate:.0f}/sec), Matching so far: {len(matching_uids)}")
last_log_time = now
# Check if matches any domain
from_match = matches_domain(msg.from_, DOMAINS)
to_match = None
if not from_match:
for to_addr in (msg.to or []):
to_match = matches_domain(to_addr, DOMAINS)
if to_match:
break
if from_match or to_match:
# Also verify date since IMAP date filtering can be imprecise
msg_date = msg.date
if msg_date and hasattr(msg_date, 'date'):
msg_date = msg_date.date()
elif isinstance(msg_date, datetime):
pass # ok
if not msg_date or msg_date >= SINCE_DATE:
matching_uids.append(msg.uid)
scan_elapsed = time.time() - scan_start
log.info(f"Phase 1 complete: scanned {total_scanned} emails in {scan_elapsed/60:.1f}min")
log.info(f"Found {len(matching_uids)} matching emails")
if not matching_uids:
log.info("No matching emails found. Exiting.")
mailbox.logout()
return
# Phase 2: Download full emails and convert to PDF
log.info("\n" + "=" * 60)
log.info("Phase 2: Downloading full emails and converting to PDF...")
log.info("=" * 60)
start_time = time.time()
total_processed = 0
total_errors = 0
def reconnect_mailbox():
"""Reconnect to IMAP with retry."""
for attempt in range(5):
try:
log.info(f"Reconnecting... attempt {attempt+1}")
mb = MailBox(IMAP_SERVER).login(imap_user, imap_pass, initial_folder=GMAIL_FOLDER)
log.info("Reconnected!")
return mb
except Exception as e:
log.warning(f"Reconnect failed: {e}")
time.sleep(10 * (attempt + 1))
log.error("Failed to reconnect after 5 attempts")
sys.exit(1)
for idx, uid in enumerate(matching_uids, 1):
if str(uid) in processed:
log.info(f"[{idx}/{len(matching_uids)}] SKIP (already processed) UID={uid}")
continue
elapsed = time.time() - start_time
if idx > 1:
eta = (elapsed / (idx - 1)) * (len(matching_uids) - idx + 1)
else:
eta = 0
log.info(f"[{idx}/{len(matching_uids)}] Downloading UID={uid} | ETA: {eta/60:.1f}m")
try:
# Fetch full message
msgs = list(mailbox.fetch(
AND(uid=uid),
headers_only=False,
mark_seen=False,
))
if not msgs:
log.warning(f" Could not fetch UID={uid}")
total_errors += 1
save_progress(uid, processed)
continue
msg = msgs[0]
# Build email info
subject = msg.subject or "(Без темы)"
from_addr = msg.from_ or "unknown"
date_str = msg.date_str or "unknown"
# Determine matching domain
match_domain = matches_domain(from_addr, DOMAINS)
if not match_domain:
for to_addr in (msg.to or []):
match_domain = matches_domain(to_addr, DOMAINS)
if match_domain:
break
if not match_domain:
match_domain = "other"
safe_subject = sanitize_filename(subject)
safe_from = sanitize_filename(from_addr.split('<')[-1].rstrip('>').split('@')[0], 30)
date_part = msg.date.strftime('%Y-%m-%d') if msg.date else 'unknown'
filename = f"{date_part}_{safe_from}_{safe_subject}.pdf"
if len(filename) > 150:
filename = filename[:150] + ".pdf"
# Build HTML for email body
html_content = build_email_html(msg)
pdf_parts = []
# Convert body to PDF
body_pdf = html_to_pdf_stream(html_content)
if body_pdf:
pdf_parts.append(body_pdf)
# Convert attachments to PDF
if msg.attachments:
log.info(f" Has {len(msg.attachments)} attachment(s)")
for att in msg.attachments:
try:
att_pdf = convert_attachment_to_pdf(
att.payload, att.filename, att.content_type
)
if att_pdf:
pdf_parts.append(att_pdf)
except Exception as e:
log.warning(f" Failed to convert attachment {att.filename}: {e}")
# Merge all PDFs
if pdf_parts:
merged_pdf = merge_pdfs(pdf_parts)
if merged_pdf:
# Save to domain folder
domain_folder = BASE_OUTPUT / sanitize_filename(match_domain, 50)
domain_folder.mkdir(parents=True, exist_ok=True)
filepath_domain = domain_folder / filename
filepath_domain.write_bytes(merged_pdf)
# Save to all folder
filepath_all = ALL_FOLDER / f"{match_domain}_{filename}"
filepath_all.write_bytes(merged_pdf)
log.info(f" SAVED: {filename}")
total_processed += 1
else:
log.warning(f" Failed to create merged PDF")
total_errors += 1
else:
log.warning(f" No content to convert")
total_errors += 1
# Save progress
save_progress(uid, processed)
except Exception as e:
# Check if it's a socket error — try to reconnect
if 'socket error' in str(e) or 'EOF' in str(e) or 'abort' in str(e):
log.warning(f"Connection lost, trying to reconnect...")
mailbox = reconnect_mailbox()
# Don't mark as processed, retry next time
total_errors += 1
continue
else:
log.error(f" ERROR processing UID={uid}: {e}", exc_info=True)
total_errors += 1
save_progress(uid, processed)
mailbox.logout()
# Summary
total_time = time.time() - start_time
summary_text = f"""
📦 <b>ОТЧЕТ ПО ЭКСПОРТУ ПОЧТЫ (Mutt)</b>
📅 <b>Дата:</b> {datetime.now().strftime('%Y-%m-%d %H:%M')}
📧 <b>Просканировано:</b> {total_scanned}
🎯 <b>Найдено (фильтр):</b> {len(matching_uids)}
<b>Обработано (новых):</b> {total_processed}
<b>Ошибок:</b> {total_errors}
<b>Время:</b> {total_time/60:.1f} мин.
📁 <i>Все файлы сохранены в PDF и готовы к загрузке в NotebookLM!</i>
"""
log.info("\n" + "=" * 60)
log.info("EXPORT COMPLETE!")
log.info(f"Total scanned: {total_scanned}")
log.info(f"Matching: {len(matching_uids)}")
log.info(f"Processed this run: {total_processed}")
log.info(f"Errors: {total_errors}")
log.info(f"Total time: {total_time/60:.1f} minutes")
log.info("=" * 60)
# Telegram Notification (only if processed > 0)
if total_processed > 0:
try:
import requests
BOT_TOKEN = "8725618164:AAH1tGalq-pw1l0t4P5c0sdLkCVJdh7IE7M"
CHAT_ID = "197957361"
url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage"
params = {
"chat_id": CHAT_ID,
"text": "📬 <b>ВАЖНОЕ ОБНОВЛЕНИЕ ПОЧТЫ!</b>\n" + summary_text + "\n🚀 <i>Пора обновить источники в NotebookLM!</i>",
"parse_mode": "HTML"
}
# Use proxy if needed
proxies = {"https": "socks5h://127.0.0.1:10808"}
requests.post(url, json=params, proxies=proxies, timeout=20)
log.info("✅ Telegram notification sent.")
except Exception as e:
log.error(f"❌ Failed to send Telegram notification: {e}")
if __name__ == '__main__':
main()

404
export_phase2.py Normal file
View file

@ -0,0 +1,404 @@
#!/usr/bin/env python3
"""
Phase 2 only: Download matching UIDs and convert to PDF.
Reads UIDs from .export_progress (or scans fresh if not found).
Reconnects for each email to avoid Gmail IMAP drops.
"""
import os
import sys
import re
import time
import logging
from pathlib import Path
from datetime import datetime, date
from imap_tools import MailBox, AND
from weasyprint import HTML
from fpdf import FPDF
import fitz # PyMuPDF
# === CONFIG ===
IMAP_SERVER = "imap.gmail.com"
GMAIL_FOLDER = "[Gmail]/Вся почта"
MUTT_CONF = Path(__file__).parent / ".muttrc"
if not MUTT_CONF.exists():
MUTT_CONF = Path.home() / ".muttrc"
DOMAINS = [
"gosuslugi.ru", "dom.gosuslugi.ru", "gov.ru", "duma.gov.ru",
"mvd.gov.ru", "mvd.ru", "rkn.gov.ru", "nalog.gov.ru", "nalog.ru",
"genproc.gov.ru", "pfr.gov.ru", "fss.ru", "rospotrebnadzor.ru",
"russianpost.ru", "mailop.ru", "73.mailop.ru", "uk-service.ru",
"ulgss.ru", "ulgov.ru", "ulgkh.ru", "dgi.ru", "mos.ru", "pfrf.ru",
"fsin.gov.ru", "skrf.ru", "epp.genproc.gov.ru", "ugpr.ru",
"fas.gov.ru", "minstroyrf.gov.ru", "gkh.ru", "sudrf.ru",
]
SINCE_DATE = date(2025, 12, 20)
BASE_OUTPUT = Path(__file__).parent / "exported_emails"
ALL_FOLDER = BASE_OUTPUT / "all"
PROGRESS_FILE = Path(__file__).parent / ".export_progress"
PHASE2_PROGRESS = Path(__file__).parent / ".phase2_progress"
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
handlers=[
logging.FileHandler(Path(__file__).parent / "export.log", encoding="utf-8"),
logging.StreamHandler(sys.stdout),
],
)
log = logging.getLogger(__name__)
def parse_mutt_config():
config = {}
with open(MUTT_CONF) as f:
for line in f:
line = line.strip()
if line.startswith('#') or not line:
continue
match = re.match(r'set\s+(\w+)\s*=\s*"([^"]*)"', line)
if not match:
match = re.match(r'set\s+(\w+)\s*=\s*(\S+)', line)
if match:
config[match.group(1)] = match.group(2)
return config
def sanitize_filename(name, max_len=80):
name = re.sub(r'[<>:"/\\|?*\x00-\x1f]', '_', name)
name = re.sub(r'\s+', ' ', name).strip()
return name[:max_len]
def matches_domain(addr, domains):
if not addr:
return None
addr_lower = addr.lower()
for domain in domains:
if domain.lower() in addr_lower:
return domain
return None
def html_to_pdf_stream(html_content):
try:
return HTML(string=html_content).write_pdf()
except Exception as e:
log.warning(f"weasyprint failed: {e}")
return html_to_pdf_fpdf(html_content)
def html_to_pdf_fpdf(html_content):
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_content, 'lxml')
text = soup.get_text(separator='\n')
pdf = FPDF()
pdf.add_page()
pdf.add_font('DejaVu', '', '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', uni=True)
pdf.add_font('DejaVu', 'B', '/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf', uni=True)
pdf.set_font('DejaVu', '', 10)
lines = [line for line in text.split('\n') if line.strip()]
for line in lines:
pdf.multi_cell(0, 6, line)
pdf.ln(1)
return pdf.output()
def convert_attachment_to_pdf(data, filename, content_type):
ext = Path(filename).suffix.lower()
try:
if ext in ('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp', '.svg'):
pdf = FPDF()
pdf.add_page()
import io
from PIL import Image
img = Image.open(io.BytesIO(data))
w_px, h_px = img.size
w_mm = w_px * 25.4 / 96
h_mm = h_px * 25.4 / 96
page_w = pdf.w - 20
scale = min(page_w / w_mm, (pdf.h - 20) / h_mm, 1.0)
import tempfile
with tempfile.NamedTemporaryFile(suffix=ext, delete=False) as tmp:
tmp.write(data)
tmp_path = tmp.name
try:
pdf.image(tmp_path, x=10, y=10, w=w_mm*scale, h=h_mm*scale)
finally:
os.unlink(tmp_path)
return pdf.output()
elif ext in ('.doc', '.docx', '.xls', '.xlsx'):
import tempfile, subprocess
with tempfile.TemporaryDirectory() as tmpdir:
src = Path(tmpdir) / filename
src.write_bytes(data)
subprocess.run(
['libreoffice', '--headless', '--convert-to', 'pdf',
'--outdir', tmpdir, str(src)],
capture_output=True, timeout=120
)
pdf_path = src.with_suffix('.pdf')
if pdf_path.exists():
return pdf_path.read_bytes()
elif ext == '.pdf':
return data
elif ext in ('.txt', '.csv', '.log', '.xml', '.html', '.htm'):
try:
text = data.decode('utf-8', errors='replace')
except:
text = data.decode('latin-1', errors='replace')
return html_to_pdf_fpdf(text)
else:
info = f"Attachment: {filename}\nType: {content_type}\nSize: {len(data)} bytes\n\n[Binary content - not converted]"
return html_to_pdf_fpdf(info)
except Exception as e:
log.warning(f"Failed to convert {filename}: {e}")
info = f"Attachment: {filename}\nType: {content_type}\nSize: {len(data)} bytes\n\nConversion failed: {e}"
return html_to_pdf_fpdf(info)
def merge_pdfs(pdf_list):
if not pdf_list:
return None
if len(pdf_list) == 1:
return pdf_list[0]
merger = fitz.open()
for pdf_bytes in pdf_list:
try:
doc = fitz.open(stream=pdf_bytes, filetype="pdf")
merger.insert_pdf(doc)
except Exception as e:
log.warning(f"Failed to merge PDF section: {e}")
output = merger.tobytes()
merger.close()
return output
def build_email_html(msg):
subject = msg.subject or "(Без темы)"
from_addr = msg.from_ or "unknown"
to_addr = ", ".join(msg.to) if msg.to else "unknown"
cc_addr = ", ".join(msg.cc) if msg.cc else ""
date_str = msg.date_str or str(msg.date) if msg.date else "unknown"
body_html = msg.html
if not body_html and msg.text:
text = msg.text
text_escaped = text.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
body_html = text_escaped.replace('\n', '<br>\n')
elif not body_html:
body_html = "<p><i>(Нет тела письма)</i></p>"
att_info = ""
if msg.attachments:
items = [f'<li>{a.filename} ({a.content_type}, {a.size} bytes)</li>' for a in msg.attachments]
att_info = '<h3 style="color:#555;">Вложения:</h3><ul>' + ''.join(items) + '</ul>'
return f"""
<html><head><meta charset="utf-8">
<style>
body {{ font-family: 'DejaVu Sans', Arial, sans-serif; font-size: 12px; margin: 20px; color: #333; }}
.header {{ background: #f0f4f8; padding: 15px; border-radius: 5px; margin-bottom: 15px; border-left: 4px solid #3b82f6; }}
.header h2 {{ margin: 0 0 10px 0; font-size: 16px; color: #1e40af; }}
.header table {{ width: 100%; }}
.header td {{ padding: 3px 5px; vertical-align: top; }}
.header td:first-child {{ font-weight: bold; width: 80px; color: #555; }}
.body {{ line-height: 1.6; }}
.attachments {{ margin-top: 20px; padding: 10px; background: #f9fafb; border-radius: 3px; }}
.attachments li {{ margin: 3px 0; color: #666; }}
</style></head><body>
<div class="header">
<h2>{subject}</h2>
<table>
<tr><td>От:</td><td>{from_addr}</td></tr>
<tr><td>Кому:</td><td>{to_addr}</td></tr>
{f'<tr><td>Копия:</td><td>{cc_addr}</td></tr>' if cc_addr else ''}
<tr><td>Дата:</td><td>{date_str}</td></tr>
</table>
</div>
<div class="body">{body_html}</div>
{f'<div class="attachments">{att_info}</div>' if att_info else ''}
</body></html>"""
def load_phase2_progress():
"""Load set of UIDs already converted to PDF."""
if PHASE2_PROGRESS.exists():
return set(PHASE2_PROGRESS.read_text().strip().splitlines())
return set()
def save_phase2_progress(uid, processed_set):
processed_set.add(str(uid))
PHASE2_PROGRESS.write_text("\n".join(processed_set))
def main():
log.info("=" * 60)
log.info("Phase 2: Download & Convert to PDF")
log.info("=" * 60)
config = parse_mutt_config()
imap_user = config.get('imap_user', '')
imap_pass = config.get('imap_pass', '')
if not imap_user or imap_user == 'your.email@gmail.com':
log.error("No credentials in .muttrc!")
sys.exit(1)
BASE_OUTPUT.mkdir(parents=True, exist_ok=True)
ALL_FOLDER.mkdir(parents=True, exist_ok=True)
# Load UIDs from phase1 progress
if not PROGRESS_FILE.exists():
log.error("No .export_progress found. Run phase 1 first.")
sys.exit(1)
all_uids = [line.strip() for line in PROGRESS_FILE.read_text().strip().splitlines() if line.strip()]
log.info(f"Total UIDs from phase 1: {len(all_uids)}")
# Load phase 2 progress (already converted)
phase2_done = load_phase2_progress()
log.info(f"Already converted: {len(phase2_done)}")
remaining = [uid for uid in all_uids if uid not in phase2_done]
log.info(f"Remaining to convert: {len(remaining)}")
if not remaining:
log.info("All done!")
return
start_time = time.time()
total_processed = 0
total_errors = 0
for idx, uid in enumerate(remaining, 1):
elapsed = time.time() - start_time
if idx > 1:
eta = (elapsed / (idx - 1)) * (len(remaining) - idx + 1)
else:
eta = 0
log.info(f"[{idx}/{len(remaining)}] UID={uid} | ETA: {eta/60:.1f}m")
# Reconnect for each email
mailbox = None
for attempt in range(3):
try:
mailbox = MailBox(IMAP_SERVER).login(imap_user, imap_pass, initial_folder=GMAIL_FOLDER)
break
except Exception as e:
log.warning(f"Connect attempt {attempt+1} failed: {e}")
time.sleep(5 * (attempt + 1))
mailbox = None
if not mailbox:
log.error(f"Failed to connect for UID={uid}")
total_errors += 1
continue
try:
msgs = list(mailbox.fetch(
AND(uid=uid),
headers_only=False,
mark_seen=False,
))
if not msgs:
log.warning(f" Could not fetch UID={uid}")
total_errors += 1
save_phase2_progress(uid, phase2_done)
continue
msg = msgs[0]
subject = msg.subject or "(Без темы)"
from_addr = msg.from_ or "unknown"
match_domain = matches_domain(from_addr, DOMAINS)
if not match_domain:
for to_addr in (msg.to or []):
match_domain = matches_domain(to_addr, DOMAINS)
if match_domain:
break
if not match_domain:
match_domain = "other"
safe_subject = sanitize_filename(subject)
safe_from = sanitize_filename(from_addr.split('<')[-1].rstrip('>').split('@')[0], 30)
date_part = msg.date.strftime('%Y-%m-%d') if msg.date else 'unknown'
filename = f"{date_part}_{safe_from}_{safe_subject}.pdf"
if len(filename) > 150:
filename = filename[:150] + ".pdf"
html_content = build_email_html(msg)
pdf_parts = []
body_pdf = html_to_pdf_stream(html_content)
if body_pdf:
pdf_parts.append(body_pdf)
if msg.attachments:
log.info(f" {len(msg.attachments)} attachment(s)")
for att in msg.attachments:
try:
att_pdf = convert_attachment_to_pdf(
att.payload, att.filename, att.content_type
)
if att_pdf:
pdf_parts.append(att_pdf)
except Exception as e:
log.warning(f" Attachment convert failed {att.filename}: {e}")
if pdf_parts:
merged_pdf = merge_pdfs(pdf_parts)
if merged_pdf:
domain_folder = BASE_OUTPUT / sanitize_filename(match_domain, 50)
domain_folder.mkdir(parents=True, exist_ok=True)
(domain_folder / filename).write_bytes(merged_pdf)
(ALL_FOLDER / f"{match_domain}_{filename}").write_bytes(merged_pdf)
log.info(f" SAVED: {filename}")
total_processed += 1
else:
log.warning(f" Failed to merge PDF")
total_errors += 1
else:
log.warning(f" No content")
total_errors += 1
save_phase2_progress(uid, phase2_done)
except Exception as e:
log.error(f" ERROR UID={uid}: {e}")
total_errors += 1
finally:
if mailbox:
try:
mailbox.logout()
except:
pass
# Small delay to avoid Gmail rate limiting
time.sleep(0.5)
total_time = time.time() - start_time
log.info("\n" + "=" * 60)
log.info("PHASE 2 COMPLETE!")
log.info(f"Processed: {total_processed}")
log.info(f"Errors: {total_errors}")
log.info(f"Time: {total_time/60:.1f} min")
log.info(f"Total PDFs: {len(list(ALL_FOLDER.glob('*.pdf')))}")
log.info("=" * 60)
if __name__ == '__main__':
main()

428
report_detailed.txt Normal file
View file

@ -0,0 +1,428 @@
📊 **ПОЛНЫЙ ОТЧЁТ ПО ПЕРЕПИСКЕ С ОРГАНАМИ ВЛАСТИ**
📅 Дата формирования: 12.04.2026 18:48
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
────────────────────────────────────────────────
**🟦 Госуслуги**
────────────────────────────────────────────────
№ │ Дата │ Статус │ Вх. № │ Тема
────┼────────────┼───────────────┼────────────────────┼───────────────────────────────
1 │ 2025-12-20 │ ⏳ Нет ответа │ o-reply │ Примите участие в конкурсе «Лиде...
2 │ 2025-12-22 │ ⏳ Нет ответа │ o-reply │ Оцените работу социальных органи...
3 │ 2025-12-23 │ ⏳ Нет ответа │ o-reply │ Присоединяйтесь к чату вашего до...
4 │ 2025-12-25 │ ⏳ Нет ответа │ o-reply │ Re_ Присоединяйтесь к чату вашег...
5 │ 2025-12-27 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
6 │ 2025-12-29 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
7 │ 2025-12-30 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
8 │ 2025-12-30 │ ⏳ Нет ответа │ o-reply │ Изменены сведения в Реестре воин...
9 │ 2025-12-30 │ Формальная ⚠️ │ 73-2025-28074 │ ГИС ЖКХ. Взято в работу обращени...
10 │ 2025-12-31 │ ⏳ Нет ответа │ o-reply │ С наступающим Новым годом!
11 │ 2026-01-03 │ Формальная ⚠️ │ 73-2026-26 │ ГИС ЖКХ. Взято в работу обращени...
12 │ 2026-01-03 │ Формальная ⚠️ │ 73-2026-26 │ ГИС ЖКХ. Завершены работы по обр...
13 │ 2026-01-03 │ Формальная ⚠️ │ 73-2026-26 │ ГИС ЖКХ. Ответ на обращение № 73...
14 │ 2026-01-04 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
15 │ 2026-01-07 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
16 │ 2026-01-12 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
17 │ 2026-01-13 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
18 │ 2026-01-13 │ Формальная ⚠️ │ 73-2025-28128 │ ГИС ЖКХ. Взято в работу обращени...
19 │ 2026-01-13 │ Формальная ⚠️ │ 73-2026-681 │ ГИС ЖКХ. Взято в работу обращени...
20 │ 2026-01-14 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
21 │ 2026-01-14 │ Формальная ⚠️ │ 20260100104989 │ Доставлено информационное сообще...
22 │ 2026-01-16 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
23 │ 2026-01-16 │ ⏳ Нет ответа │ o-reply │ Новое голосование по вашему дому
24 │ 2026-01-18 │ Формальная ⚠️ │ o-reply │ Ваше обращение передано на испол...
25 │ 2026-01-18 │ Формальная ⚠️ │ o-reply │ Ваше обращение поступило на моде...
26 │ 2026-01-18 │ Формальная ⚠️ │ o-reply │ Ваше обращение принято модератором
27 │ 2026-01-18 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
28 │ 2026-01-19 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
29 │ 2026-01-19 │ Формальная ⚠️ │ 73-2026-1580 │ ГИС ЖКХ. Взято в работу обращени...
30 │ 2026-01-20 │ Формальная ⚠️ │ o-reply │ Ваше обращение рассмотрено
31 │ 2026-01-22 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
32 │ 2026-01-22 │ Формальная ⚠️ │ 73-2025-28074 │ ГИС ЖКХ. Завершены работы по обр...
33 │ 2026-01-22 │ Формальная ⚠️ │ 73-2026-681 │ ГИС ЖКХ. Завершены работы по обр...
34 │ 2026-01-22 │ Формальная ⚠️ │ 73-2025-28074 │ ГИС ЖКХ. Ответ на обращение № 73...
35 │ 2026-01-22 │ Формальная ⚠️ │ 73-2026-681 │ ГИС ЖКХ. Ответ на обращение № 73...
36 │ 2026-01-23 │ ⏳ Нет ответа │ o-reply │ «Цифровой марафон» от Сбера
37 │ 2026-01-24 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
38 │ 2026-01-25 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
39 │ 2026-01-26 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
40 │ 2026-01-26 │ ⏳ Нет ответа │ o-reply │ Началось собрание собственников ...
41 │ 2026-01-27 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
42 │ 2026-01-27 │ Формальная ⚠️ │ 73-2026-2441 │ ГИС ЖКХ. Взято в работу обращени...
43 │ 2026-01-27 │ Формальная ⚠️ │ 73-2026-2619 │ ГИС ЖКХ. Взято в работу обращени...
44 │ 2026-01-27 │ Формальная ⚠️ │ 73-2026-2645 │ ГИС ЖКХ. Взято в работу обращени...
45 │ 2026-01-27 │ Формальная ⚠️ │ 73-2025-28128 │ ГИС ЖКХ. Завершены работы по обр...
46 │ 2026-01-27 │ Формальная ⚠️ │ 73-2025-28128 │ ГИС ЖКХ. Ответ на обращение № 73...
47 │ 2026-01-28 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
48 │ 2026-01-28 │ Формальная ⚠️ │ 73-2026-2766 │ ГИС ЖКХ. Взято в работу обращени...
49 │ 2026-01-29 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
50 │ 2026-01-29 │ ⏳ Нет ответа │ o-reply │ Отзыв по процессу получения госу...
51 │ 2026-01-29 │ ⏳ Нет ответа │ o-reply │ Получение онлайн-выписки
52 │ 2026-01-29 │ Формальная ⚠️ │ 73-2026-2898 │ ГИС ЖКХ. Взято в работу обращени...
53 │ 2026-01-29 │ Формальная ⚠️ │ 73-2026-2900 │ ГИС ЖКХ. Взято в работу обращени...
54 │ 2026-01-30 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
55 │ 2026-01-30 │ Формальная ⚠️ │ 73-2026-2969 │ ГИС ЖКХ. Взято в работу обращени...
56 │ 2026-02-01 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
57 │ 2026-02-01 │ ⏳ Нет ответа │ o-reply │ Изменены сведения в Реестре воин...
58 │ 2026-02-02 │ Формальная ⚠️ │ 73-2026-3108 │ ГИС ЖКХ. Взято в работу обращени...
59 │ 2026-02-02 │ Формальная ⚠️ │ 73-2026-3294 │ ГИС ЖКХ. Взято в работу обращени...
60 │ 2026-02-02 │ Формальная ⚠️ │ 73-2026-3295 │ ГИС ЖКХ. Взято в работу обращени...
61 │ 2026-02-04 │ ⏳ Нет ответа │ o-reply │ Узнавайте важное о новостройках ...
62 │ 2026-02-05 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
63 │ 2026-02-05 │ ⏳ Нет ответа │ o-reply │ У вас есть непрочитанное сообщен...
64 │ 2026-02-06 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
65 │ 2026-02-06 │ ⏳ Нет ответа │ o-reply │ Присоединяйтесь к официальному ч...
66 │ 2026-02-06 │ Формальная ⚠️ │ 73-2026-4093 │ ГИС ЖКХ. Взято в работу обращени...
67 │ 2026-02-06 │ Формальная ⚠️ │ 20260200109025 │ Доставлено информационное сообще...
68 │ 2026-02-07 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
69 │ 2026-02-08 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
70 │ 2026-02-09 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
71 │ 2026-02-09 │ Формальная ⚠️ │ 73-2026-4257 │ ГИС ЖКХ. Взято в работу обращени...
72 │ 2026-02-09 │ Формальная ⚠️ │ 73-2026-4385 │ ГИС ЖКХ. Взято в работу обращени...
73 │ 2026-02-09 │ Формальная ⚠️ │ 73-2026-1580 │ ГИС ЖКХ. Завершены работы по обр...
74 │ 2026-02-09 │ Формальная ⚠️ │ 73-2026-2441 │ ГИС ЖКХ. Завершены работы по обр...
75 │ 2026-02-09 │ Формальная ⚠️ │ 73-2026-1580 │ ГИС ЖКХ. Ответ на обращение № 73...
76 │ 2026-02-09 │ Формальная ⚠️ │ 73-2026-2441 │ ГИС ЖКХ. Ответ на обращение № 73...
77 │ 2026-02-10 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
78 │ 2026-02-10 │ Формальная ⚠️ │ 73-2026-2619 │ ГИС ЖКХ. Завершены работы по обр...
79 │ 2026-02-10 │ Формальная ⚠️ │ 73-2026-2645 │ ГИС ЖКХ. Завершены работы по обр...
80 │ 2026-02-10 │ Формальная ⚠️ │ 73-2026-2766 │ ГИС ЖКХ. Завершены работы по обр...
81 │ 2026-02-10 │ Формальная ⚠️ │ 73-2026-2898 │ ГИС ЖКХ. Завершены работы по обр...
82 │ 2026-02-10 │ Формальная ⚠️ │ 73-2026-3108 │ ГИС ЖКХ. Завершены работы по обр...
83 │ 2026-02-10 │ Формальная ⚠️ │ 73-2026-3294 │ ГИС ЖКХ. Завершены работы по обр...
84 │ 2026-02-10 │ Формальная ⚠️ │ 73-2026-3295 │ ГИС ЖКХ. Завершены работы по обр...
85 │ 2026-02-10 │ Формальная ⚠️ │ 73-2026-2619 │ ГИС ЖКХ. Ответ на обращение № 73...
86 │ 2026-02-10 │ Формальная ⚠️ │ 73-2026-2645 │ ГИС ЖКХ. Ответ на обращение № 73...
87 │ 2026-02-10 │ Формальная ⚠️ │ 73-2026-2766 │ ГИС ЖКХ. Ответ на обращение № 73...
88 │ 2026-02-10 │ Формальная ⚠️ │ 73-2026-2898 │ ГИС ЖКХ. Ответ на обращение № 73...
89 │ 2026-02-10 │ Формальная ⚠️ │ 73-2026-3108 │ ГИС ЖКХ. Ответ на обращение № 73...
90 │ 2026-02-10 │ Формальная ⚠️ │ 73-2026-3294 │ ГИС ЖКХ. Ответ на обращение № 73...
91 │ 2026-02-10 │ Формальная ⚠️ │ 73-2026-3295 │ ГИС ЖКХ. Ответ на обращение № 73...
92 │ 2026-02-11 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
93 │ 2026-02-11 │ Формальная ⚠️ │ 73-2026-4869 │ ГИС ЖКХ. Взято в работу обращени...
94 │ 2026-02-12 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
95 │ 2026-02-12 │ Формальная ⚠️ │ 73-2026-5028 │ ГИС ЖКХ. Взято в работу обращени...
96 │ 2026-02-12 │ Формальная ⚠️ │ 73-2026-5029 │ ГИС ЖКХ. Взято в работу обращени...
97 │ 2026-02-12 │ Формальная ⚠️ │ 73-2026-5075 │ ГИС ЖКХ. Взято в работу обращени...
98 │ 2026-02-13 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
99 │ 2026-02-13 │ Формальная ⚠️ │ 73-2026-4257 │ ГИС ЖКХ. Завершены работы по обр...
100 │ 2026-02-13 │ Формальная ⚠️ │ 73-2026-4257 │ ГИС ЖКХ. Ответ на обращение № 73...
101 │ 2026-02-14 │ ⏳ Нет ответа │ o-reply │ Новое голосование по вашему дому
102 │ 2026-02-15 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
103 │ 2026-02-15 │ ⏳ Нет ответа │ o-reply │ У вас есть непрочитанное сообщен...
104 │ 2026-02-16 │ Формальная ⚠️ │ o-reply │ Ваше обращение поступило на моде...
105 │ 2026-02-16 │ Формальная ⚠️ │ o-reply │ Ваше обращение принято модератором
106 │ 2026-02-16 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
107 │ 2026-02-16 │ Формальная ⚠️ │ o-reply │ Подача обращения в органы прокур...
108 │ 2026-02-17 │ Формальная ⚠️ │ o-reply │ Ваше обращение передано на испол...
109 │ 2026-02-17 │ Формальная ⚠️ │ o-reply │ Ваше обращение поступило на моде...
110 │ 2026-02-17 │ Формальная ⚠️ │ o-reply │ Ваше обращение принято модератором
111 │ 2026-02-17 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
112 │ 2026-02-17 │ ⏳ Нет ответа │ o-reply │ Отзыв по процессу получения госу...
113 │ 2026-02-17 │ Формальная ⚠️ │ 73-2026-5818 │ ГИС ЖКХ. Взято в работу обращени...
114 │ 2026-02-18 │ Формальная ⚠️ │ o-reply │ Ваше обращение взято в работу
115 │ 2026-02-18 │ Формальная ⚠️ │ o-reply │ Ваше обращение передано на испол...
116 │ 2026-02-18 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
117 │ 2026-02-18 │ ⏳ Нет ответа │ o-reply │ Оплатите госпошлину
118 │ 2026-02-19 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
119 │ 2026-02-19 │ Формальная ⚠️ │ 73-2026-6151 │ ГИС ЖКХ. Взято в работу обращени...
120 │ 2026-02-19 │ Формальная ⚠️ │ 73-2026-6152 │ ГИС ЖКХ. Взято в работу обращени...
121 │ 2026-02-20 │ Формальная ⚠️ │ o-reply │ Ваше обращение передано на испол...
122 │ 2026-02-20 │ Формальная ⚠️ │ o-reply │ Ваше обращение рассмотрено
123 │ 2026-02-24 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
124 │ 2026-02-24 │ ⏳ Нет ответа │ o-reply │ Началось собрание собственников ...
125 │ 2026-02-24 │ ⏳ Нет ответа │ o-reply │ Участвуйте в четвёртом сезоне «Б...
126 │ 2026-02-24 │ Формальная ⚠️ │ 20260200109025 │ Доставлено информационное сообще...
127 │ 2026-02-26 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
128 │ 2026-02-27 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
129 │ 2026-02-27 │ ⏳ Нет ответа │ o-reply │ Отзыв по процессу получения госу...
130 │ 2026-02-27 │ ⏳ Нет ответа │ o-reply │ Предоставление сведений из ЕГРН
131 │ 2026-02-27 │ Формальная ⚠️ │ 73-2026-2969 │ ГИС ЖКХ. Завершены работы по обр...
132 │ 2026-02-27 │ Формальная ⚠️ │ 73-2026-4869 │ ГИС ЖКХ. Завершены работы по обр...
133 │ 2026-02-27 │ Формальная ⚠️ │ 73-2026-5818 │ ГИС ЖКХ. Завершены работы по обр...
134 │ 2026-02-27 │ Формальная ⚠️ │ 73-2026-2969 │ ГИС ЖКХ. Ответ на обращение № 73...
135 │ 2026-02-27 │ Формальная ⚠️ │ 73-2026-4869 │ ГИС ЖКХ. Ответ на обращение № 73...
136 │ 2026-02-27 │ Формальная ⚠️ │ 73-2026-5818 │ ГИС ЖКХ. Ответ на обращение № 73...
137 │ 2026-03-01 │ ⏳ Нет ответа │ o-reply │ Блокировка абонентского номера
138 │ 2026-03-01 │ ⏳ Нет ответа │ o-reply │ Отзыв по процессу получения госу...
139 │ 2026-03-02 │ Формальная ⚠️ │ 73-2026-6151 │ ГИС ЖКХ. Завершены работы по обр...
140 │ 2026-03-02 │ Формальная ⚠️ │ 73-2026-6151 │ ГИС ЖКХ. Ответ на обращение № 73...
141 │ 2026-03-03 │ Формальная ⚠️ │ 73-2026-2900 │ ГИС ЖКХ. Завершены работы по обр...
142 │ 2026-03-03 │ Формальная ⚠️ │ 73-2026-2900 │ ГИС ЖКХ. Ответ на обращение № 73...
143 │ 2026-03-04 │ Формальная ⚠️ │ 73-2026-4093 │ ГИС ЖКХ. Завершены работы по обр...
144 │ 2026-03-04 │ Формальная ⚠️ │ 73-2026-5028 │ ГИС ЖКХ. Завершены работы по обр...
145 │ 2026-03-04 │ Формальная ⚠️ │ 73-2026-5075 │ ГИС ЖКХ. Завершены работы по обр...
146 │ 2026-03-04 │ Формальная ⚠️ │ 73-2026-4093 │ ГИС ЖКХ. Ответ на обращение № 73...
147 │ 2026-03-04 │ Формальная ⚠️ │ 73-2026-5028 │ ГИС ЖКХ. Ответ на обращение № 73...
148 │ 2026-03-04 │ Формальная ⚠️ │ 73-2026-5075 │ ГИС ЖКХ. Ответ на обращение № 73...
149 │ 2026-03-05 │ ⏳ Нет ответа │ o-reply │ Голосуйте за лучшие проекты прем...
150 │ 2026-03-05 │ Формальная ⚠️ │ 73-2026-4385 │ ГИС ЖКХ. Завершены работы по обр...
151 │ 2026-03-05 │ Формальная ⚠️ │ 73-2026-4385 │ ГИС ЖКХ. Ответ на обращение № 73...
152 │ 2026-03-06 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
153 │ 2026-03-06 │ ⏳ Нет ответа │ o-reply │ У вас есть непрочитанное сообщен...
154 │ 2026-03-06 │ ⏳ Нет ответа │ o-reply │ Электронное заказное письмо
155 │ 2026-03-06 │ Формальная ⚠️ │ 20260200109025 │ Доставлено информационное сообще...
156 │ 2026-03-06 │ Формальная ⚠️ │ 20260200109025 │ Доставлено информационное сообще...
157 │ 2026-03-07 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
158 │ 2026-03-07 │ ⏳ Нет ответа │ o-reply │ Ознакомьтесь с результатами голо...
159 │ 2026-03-08 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
160 │ 2026-03-10 │ Формальная ⚠️ │ 73-2026-5029 │ ГИС ЖКХ. Завершены работы по обр...
161 │ 2026-03-10 │ Формальная ⚠️ │ 73-2026-6152 │ ГИС ЖКХ. Завершены работы по обр...
162 │ 2026-03-10 │ Формальная ⚠️ │ 73-2026-5029 │ ГИС ЖКХ. Ответ на обращение № 73...
163 │ 2026-03-10 │ Формальная ⚠️ │ 73-2026-6152 │ ГИС ЖКХ. Ответ на обращение № 73...
164 │ 2026-03-11 │ ⏳ Нет ответа │ o-reply │ Проверьте выданные согласия на п...
165 │ 2026-03-15 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
166 │ 2026-03-16 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
167 │ 2026-03-17 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
168 │ 2026-03-18 │ ⏳ Нет ответа │ o-reply │ Планируется отключение горячей воды
169 │ 2026-03-18 │ Формальная ⚠️ │ 73-2026-10010 │ ГИС ЖКХ. Взято в работу обращени...
170 │ 2026-03-18 │ Формальная ⚠️ │ 73-2026-10011 │ ГИС ЖКХ. Взято в работу обращени...
171 │ 2026-03-23 │ ⏳ Нет ответа │ o-reply │ Участвуйте в новом сезоне «Битвы...
172 │ 2026-03-24 │ ⏳ Нет ответа │ o-reply │ Присоединяйтесь к программам пом...
173 │ 2026-03-26 │ ⏳ Нет ответа │ o-reply │ Изменены сведения в Реестре воин...
174 │ 2026-03-27 │ ⏳ Нет ответа │ o-reply │ У вас есть непрочитанное сообщен...
175 │ 2026-03-27 │ Формальная ⚠️ │ 20260100104989 │ Доставлено информационное сообще...
176 │ 2026-03-31 │ ⏳ Нет ответа │ o-reply │ Электронное заказное письмо
177 │ 2026-04-01 │ ⏳ Нет ответа │ o-reply │ Вы авторизовались, используя учё...
📊 Итого по органу: 177 писем | Ответов: 97 (55%)
────────────────────────────────────────────────
**🏛 УЛГСС**
────────────────────────────────────────────────
№ │ Дата │ Статус │ Вх. № │ Тема
────┼────────────┼───────────────┼────────────────────┼───────────────────────────────
1 │ 2025-12-29 │ ⏳ Нет ответа │ — │ Test mail
2 │ 2025-12-29 │ Формальная ⚠️ │ 463-ФЗ │ Требование предоставить предложе...
3 │ 2025-12-30 │ ⏳ Нет ответа │ — │ ЛЕНКОМ 37 скан предложений по та...
4 │ 2025-12-30 │ ⏳ Нет ответа │ — │ Предложения жильцов-собственнико...
5 │ 2026-01-04 │ Формальная ⚠️ │ 2026 │ Запрос информации о статусе пред...
6 │ 2026-01-05 │ Формальная ⚠️ │ 2026 │ Запрос о работе погодника на Лен...
7 │ 2026-01-05 │ Формальная ⚠️ │ 2026 │ ТРЕБОВАНИЕ О ПРЕДОСТАВЛЕНИИ ИНФО...
8 │ 2026-01-06 │ Формальная ⚠️ │ 2026 │ О предоставлении информации о по...
9 │ 2026-01-07 │ Формальная ⚠️ │ 2026 │ Запрос информации о законности и...
10 │ 2026-01-07 │ Формальная ⚠️ │ 2026 │ Запрос о предоставлении Акта изм...
11 │ 2026-01-14 │ Формальная ⚠️ │ 2026 │ ПИСЬМО-УВЕДОМЛЕНИЕ (в ответ на в...
12 │ 2026-01-14 │ Формальная ⚠️ │ 2026 │ ТРЕБОВАНИЕ о предоставлении инфо...
13 │ 2026-01-15 │ Формальная ⚠️ │ 2026 │ ЗАПРОС о подтверждении полномочи...
14 │ 2026-01-15 │ Формальная ⚠️ │ 2026 │ О запросе информации касательно ...
15 │ 2026-01-15 │ Формальная ⚠️ │ 2026 │ О легальности размещения ТОС «Вз...
16 │ 2026-01-15 │ Формальная ⚠️ │ 2026 │ О нарушении процедуры созыва общ...
17 │ 2026-01-15 │ Формальная ⚠️ │ 2026 │ О непредоставлении проекта догов...
18 │ 2026-01-15 │ Формальная ⚠️ │ 2026 │ О несанкционированном ограничени...
19 │ 2026-01-15 │ Формальная ⚠️ │ 2026 │ О предоставлении договора с подр...
20 │ 2026-01-15 │ Формальная ⚠️ │ 2026 │ О противоречиях в расходовании с...
21 │ 2026-01-15 │ Формальная ⚠️ │ 2026 │ Об обосновании площади покоса га...
22 │ 2026-01-26 │ Формальная ⚠️ │ 2026 │ Акт выполненных работ (форма КС-...
23 │ 2026-01-26 │ Формальная ⚠️ │ 2026 │ Акт наладки погодника (ЛенКом 37)
24 │ 2026-01-26 │ Формальная ⚠️ │ 2026 │ О незаконном истребовании персон...
25 │ 2026-01-26 │ Формальная ⚠️ │ 2026 │ Об ограничении доступа к информа...
26 │ 2026-01-27 │ Формальная ⚠️ │ 2026 │ [REQ-2026-KS-TREE] Требование о ...
27 │ 2026-01-27 │ ⏳ Нет ответа │ 2026 │ [REQ-2026-PB-37] Запрос разрешит...
28 │ 2026-01-27 │ Формальная ⚠️ │ 2026 │ [REQ-2026-PODRYAD] Запрос копий ...
29 │ 2026-01-27 │ ⏳ Нет ответа │ 2026 │ [REQ-2026-REM5K] Запрос документ...
30 │ 2026-01-29 │ ⏳ Нет ответа │ 2026 │ (Без темы)
31 │ 2026-02-02 │ Формальная ⚠️ │ — │ ВОЗРАЖЕНИЕ на ответ № 217 от 28....
32 │ 2026-02-24 │ Формальная ⚠️ │ — │ Уведомление о визите
33 │ 2026-03-10 │ Формальная ⚠️ │ — │ ТРЕБОВАНИЕ В АДРЕС ДИРЕКТОРА ООО...
📊 Итого по органу: 33 писем | Ответов: 27 (82%)
────────────────────────────────────────────────
**🏢 УЛГКХ**
────────────────────────────────────────────────
№ │ Дата │ Статус │ Вх. № │ Тема
────┼────────────┼───────────────┼────────────────────┼───────────────────────────────
1 │ 2026-01-03 │ Формальная ⚠️ │ 2026 │ Управляющая организация
2 │ 2026-01-13 │ Формальная ⚠️ │ 2026 │ Fwd_ Запрос информации о статусе...
3 │ 2026-01-13 │ Формальная ⚠️ │ 2026 │ Fwd_ ТРЕБОВАНИЕ О ПРЕДОСТАВЛЕНИИ...
4 │ 2026-01-14 │ Формальная ⚠️ │ 2026 │ Fwd_ Запрос информации о законно...
5 │ 2026-01-14 │ Формальная ⚠️ │ 2026 │ Fwd_ О предоставлении информации...
6 │ 2026-01-16 │ Формальная ⚠️ │ 2026 │ Fwd_ ПИСЬМО-УВЕДОМЛЕНИЕ (в ответ...
7 │ 2026-01-16 │ Формальная ⚠️ │ 2026 │ Fwd_ ТРЕБОВАНИЕ о предоставлении...
8 │ 2026-01-22 │ Формальная ⚠️ │ 2026 │ Fwd_ Запрос о предоставлении Акт...
9 │ 2026-01-22 │ Формальная ⚠️ │ 2026 │ Fwd_ Запрос о работе погодника н...
10 │ 2026-01-22 │ ⏳ Нет ответа │ 2026 │ Fwd_ ЛЕНКОМ 37 скан предложений ...
11 │ 2026-01-22 │ Формальная ⚠️ │ 2026 │ Fwd_ О легальности размещения ТО...
12 │ 2026-01-22 │ Формальная ⚠️ │ 2026 │ Fwd_ О непредоставлении проекта ...
13 │ 2026-01-22 │ Формальная ⚠️ │ 2026 │ Fwd_ О несанкционированном огран...
14 │ 2026-01-22 │ Формальная ⚠️ │ 2026 │ Fwd_ О предоставлении договора с...
15 │ 2026-01-22 │ Формальная ⚠️ │ 2026 │ Fwd_ О противоречиях в расходова...
16 │ 2026-01-22 │ Формальная ⚠️ │ 2026 │ Fwd_ Об обосновании площади поко...
17 │ 2026-01-26 │ Формальная ⚠️ │ 2026 │ Fwd_ О нарушении процедуры созыв...
18 │ 2026-01-27 │ Формальная ⚠️ │ 2026 │ Fwd_ Акт выполненных работ (форм...
19 │ 2026-01-27 │ Формальная ⚠️ │ 2026 │ Fwd_ ЗАПРОС о подтверждении полн...
20 │ 2026-01-27 │ Формальная ⚠️ │ 2026 │ Fwd_ О запросе информации касате...
21 │ 2026-01-28 │ Формальная ⚠️ │ 2026 │ Fwd_ Акт наладки погодника (ЛенК...
22 │ 2026-01-30 │ ⏳ Нет ответа │ 2026 │ Fwd_ [REQ-2026-PB-37] Запрос раз...
23 │ 2026-01-30 │ Формальная ⚠️ │ 2026 │ Fwd_ Акт выполненных работ (форм...
24 │ 2026-01-30 │ Формальная ⚠️ │ 2026 │ Fwd_ Об ограничении доступа к ин...
25 │ 2026-02-05 │ Формальная ⚠️ │ /pdf │ Fwd_ ВОЗРАЖЕНИЕ на ответ № 217 о...
26 │ 2026-02-06 │ Формальная ⚠️ │ 2026 │ Fwd_ О незаконном истребовании п...
27 │ 2026-02-24 │ Формальная ⚠️ │ — │ Fwd_ Уведомление о визите
28 │ 2026-02-25 │ Формальная ⚠️ │ — │ Дополнительный ответ
29 │ 2026-03-12 │ Формальная ⚠️ │ /pdf │ Fwd_ ТРЕБОВАНИЕ В АДРЕС ДИРЕКТОР...
📊 Итого по органу: 29 писем | Ответов: 27 (93%)
────────────────────────────────────────────────
**🟧 Роспотребнадзор**
────────────────────────────────────────────────
№ │ Дата │ Статус │ Вх. № │ Тема
────┼────────────┼───────────────┼────────────────────┼───────────────────────────────
1 │ 2026-01-18 │ Формальная ⚠️ │ o-reply │ Информация об обращении в Роспот...
2 │ 2026-01-22 │ Формальная ⚠️ │ 73-00-04/46-329... │ Ответ № 73-00-04_46-329-2026 от ...
3 │ 2026-01-25 │ Формальная ⚠️ │ o-reply │ Информация об обращении в Роспот...
4 │ 2026-01-26 │ Формальная ⚠️ │ 73-00-04/46-382... │ Ответ № 73-00-04_46-382-2026 от ...
5 │ 2026-02-08 │ Формальная ⚠️ │ o-reply │ Информация об обращении в Роспот...
6 │ 2026-02-12 │ По существу ✅ │ 73-00-04/46-857... │ Ответ № 73-00-04_46-857-2026 от ...
7 │ 2026-02-17 │ Формальная ⚠️ │ 73-00-04/46-991... │ Ответ № 73-00-04_46-991-2026 от ...
8 │ 2026-02-24 │ Формальная ⚠️ │ 73-00-04/46-113... │ Ответ № 73-00-04_46-1135-2026 от...
9 │ 2026-03-17 │ Формальная ⚠️ │ 73-00-04/46-169... │ Ответ № 73-00-04_46-1692-2026 от...
📊 Итого по органу: 9 писем | Ответов: 9 (100%)
────────────────────────────────────────────────
**🟨 Почта России (mailop)**
────────────────────────────────────────────────
№ │ Дата │ Статус │ Вх. № │ Тема
────┼────────────┼───────────────┼────────────────────┼───────────────────────────────
1 │ 2026-01-19 │ Формальная ⚠️ │ 2026 │ ответ на обращение
2 │ 2026-01-21 │ Формальная ⚠️ │ 2026 │ Ответ Тырину А.А.
3 │ 2026-01-28 │ Формальная ⚠️ │ 2026 │ Ответ Тырину А.А.
4 │ 2026-02-05 │ Формальная ⚠️ │ /pdf │ Уведомление по обращению
5 │ 2026-02-12 │ Формальная ⚠️ │ /pdf │ Уведомление по обращению
6 │ 2026-02-12 │ Формальная ⚠️ │ /pdf │ Ответ Тырину А.А.
7 │ 2026-02-17 │ Формальная ⚠️ │ /pdf │ Уведомление по обращению
8 │ 2026-02-19 │ Формальная ⚠️ │ /pdf │ Уведомление по обращению
9 │ 2026-02-24 │ Формальная ⚠️ │ /pdf │ Ответ Тырину А.А.
📊 Итого по органу: 9 писем | Ответов: 9 (100%)
────────────────────────────────────────────────
**🟪 Правительство РФ**
────────────────────────────────────────────────
№ │ Дата │ Статус │ Вх. № │ Тема
────┼────────────┼───────────────┼────────────────────┼───────────────────────────────
1 │ 2026-01-22 │ ⏳ Нет ответа │ o-reply │ Уведомление о регистрации обраще...
2 │ 2026-01-26 │ ⏳ Нет ответа │ 73-ИОГВ-18/790исх │ Исходящий N 73-ИОГВ-18_790исх от...
3 │ 2026-01-27 │ ⏳ Нет ответа │ 491-01/73 │ №491-01_73 от 27.01.2026_ Запрос...
4 │ 2026-01-28 │ Формальная ⚠️ │ 491-01/73 │ В ответ на № 491-01_73
5 │ 2026-01-29 │ Формальная ⚠️ │ proc.gov.ru │ epp.genproc.gov.ru - Регистрация...
6 │ 2026-01-29 │ ⏳ Нет ответа │ 73-ИОГВ-18/938исх │ Исходящий N 73-ИОГВ-18_938исх от...
7 │ 2026-01-30 │ ⏳ Нет ответа │ o-reply │ Уведомление о регистрации обраще...
8 │ 2026-02-07 │ Формальная ⚠️ │ proc.gov.ru │ epp.genproc.gov.ru - Регистрация...
9 │ 2026-02-09 │ Формальная ⚠️ │ proc.gov.ru │ epp.genproc.gov.ru - Регистрация...
10 │ 2026-02-09 │ ⏳ Нет ответа │ 73-ИОГВ-18/1350исх │ Исходящий N 73-ИОГВ-18_1350исх о...
11 │ 2026-02-10 │ Формальная ⚠️ │ proc.gov.ru │ epp.genproc.gov.ru - Регистрация...
12 │ 2026-02-10 │ ⏳ Нет ответа │ 73-ИОГВ-18/1409исх │ Исходящий N 73-ИОГВ-18_1409исх о...
13 │ 2026-02-10 │ ⏳ Нет ответа │ 73-ИОГВ-18/1411исх │ Исходящий N 73-ИОГВ-18_1411исх о...
14 │ 2026-02-10 │ ⏳ Нет ответа │ 73-ИОГВ-18/1412исх │ Исходящий N 73-ИОГВ-18_1412исх о...
15 │ 2026-02-10 │ ⏳ Нет ответа │ 73-ИОГВ-18/1414исх │ Исходящий N 73-ИОГВ-18_1414исх о...
16 │ 2026-02-10 │ ⏳ Нет ответа │ 73-ИОГВ-18/1416исх │ Исходящий N 73-ИОГВ-18_1416исх о...
17 │ 2026-02-10 │ ⏳ Нет ответа │ 73-ИОГВ-18/1418исх │ Исходящий N 73-ИОГВ-18_1418исх о...
18 │ 2026-02-10 │ ⏳ Нет ответа │ 73-ИОГВ-18/1422исх │ Исходящий N 73-ИОГВ-18_1422исх о...
19 │ 2026-02-10 │ ⏳ Нет ответа │ 73-ИОГВ-18/1424исх │ Исходящий N 73-ИОГВ-18_1424исх о...
20 │ 2026-02-11 │ ⏳ Нет ответа │ o-reply │ Уведомление о регистрации обраще...
21 │ 2026-02-13 │ ⏳ Нет ответа │ 73-ИОГВ-18/1669исх │ Исходящий N 73-ИОГВ-18_1669исх о...
22 │ 2026-02-16 │ ⏳ Нет ответа │ o-reply │ О регистрации обращения Тырина А...
23 │ 2026-02-16 │ Формальная ⚠️ │ proc.gov.ru │ epp.genproc.gov.ru - Регистрация...
24 │ 2026-02-16 │ ⏳ Нет ответа │ 73-ИОГВ-18/1737исх │ Исходящий N 73-ИОГВ-18_1737исх о...
25 │ 2026-02-17 │ ⏳ Нет ответа │ 1093-01/73 │ №1093-01_73 от 16.02.2026_ О нап...
26 │ 2026-02-19 │ ⏳ Нет ответа │ o-reply │ О регистрации обращения
27 │ 2026-02-20 │ ⏳ Нет ответа │ o-reply │ О регистрации обращения
28 │ 2026-02-20 │ ⏳ Нет ответа │ 1202-01/73 │ №1202-01_73 от 20.02.2026_ О про...
29 │ 2026-02-24 │ ⏳ Нет ответа │ 73-ИОГВ-18/2005исх │ Исходящий N 73-ИОГВ-18_2005исх о...
30 │ 2026-02-25 │ ⏳ Нет ответа │ 73-ИОГВ-18/2091исх │ Исходящий N 73-ИОГВ-18_2091исх о...
31 │ 2026-02-27 │ Формальная ⚠️ │ 1377-01/73 │ №1377-01_73 от 27.02.2026_ О рас...
32 │ 2026-02-27 │ ⏳ Нет ответа │ 73-ИОГВ-18.01/2... │ Исходящий N 73-ИОГВ-18.01_2299ис...
33 │ 2026-03-02 │ ⏳ Нет ответа │ o-reply │ О регистрации обращения 73-П-ОГ_...
34 │ 2026-03-02 │ ⏳ Нет ответа │ o-reply │ О регистрации обращения
35 │ 2026-03-02 │ Формальная ⚠️ │ o-reply │ Роскомнадзор предлагает оценить ...
36 │ 2026-03-02 │ ⏳ Нет ответа │ 73-ИОГВ-18/2338исх │ Исходящий N 73-ИОГВ-18_2338исх о...
37 │ 2026-03-04 │ ⏳ Нет ответа │ 73-ИОГВ-18/2490исх │ Исходящий N 73-ИОГВ-18_2490исх о...
38 │ 2026-03-04 │ ⏳ Нет ответа │ 73-ИОГВ-18/2491исх │ Исходящий N 73-ИОГВ-18_2491исх о...
39 │ 2026-03-04 │ ⏳ Нет ответа │ 73-ИОГВ-18/2492исх │ Исходящий N 73-ИОГВ-18_2492исх о...
40 │ 2026-03-04 │ ⏳ Нет ответа │ 73-ИОГВ-18/2528исх │ Исходящий N 73-ИОГВ-18_2528исх о...
41 │ 2026-03-04 │ ⏳ Нет ответа │ 73-ИОГВ-18/2532исх │ Исходящий N 73-ИОГВ-18_2532исх о...
42 │ 2026-03-05 │ ⏳ Нет ответа │ 73-ИОГВ-18/2644исх │ Исходящий N 73-ИОГВ-18_2644исх о...
43 │ 2026-03-06 │ Формальная ⚠️ │ 73-П-06/4793исх │ Исходящий N 73-П-06_4793исх от 0...
44 │ 2026-03-10 │ ⏳ Нет ответа │ 73-ИОГВ-18/2791исх │ Исходящий N 73-ИОГВ-18_2791исх о...
45 │ 2026-03-11 │ ⏳ Нет ответа │ 1644-01/73 │ №1644-01_73 от 11.03.2026_ О про...
46 │ 2026-03-13 │ Формальная ⚠️ │ 73-П-06/5345исх │ Исходящий N 73-П-06_5345исх от 1...
47 │ 2026-03-17 │ Формальная ⚠️ │ stroyrf.gov.ru │ 5800-ОГ_04_
48 │ 2026-03-19 │ Формальная ⚠️ │ 73-П-06/5774исх │ Исходящий N 73-П-06_5774исх от 1...
49 │ 2026-03-19 │ ⏳ Нет ответа │ 73-ИОГВ-18/3247исх │ Исходящий N 73-ИОГВ-18_3247исх о...
50 │ 2026-03-20 │ Формальная ⚠️ │ 1925-01/73 │ №1925-01_73 от 20.03.2026_ О рас...
51 │ 2026-03-23 │ Формальная ⚠️ │ o-reply │ Роскомнадзор предлагает оценить ...
52 │ 2026-04-03 │ ⏳ Нет ответа │ 73-ИОГВ-18/3993исх │ Исходящий N 73-ИОГВ-18_3993исх о...
📊 Итого по органу: 52 писем | Ответов: 14 (27%)
────────────────────────────────────────────────
**🟥 МВД России**
────────────────────────────────────────────────
№ │ Дата │ Статус │ Вх. № │ Тема
────┼────────────┼───────────────┼────────────────────┼───────────────────────────────
1 │ 2026-01-27 │ Формальная ⚠️ │ o-reply │ sed_no-reply_Уведомление о стату...
2 │ 2026-01-30 │ Формальная ⚠️ │ o-reply │ sed_no-reply_Уведомление о стату...
3 │ 2026-02-06 │ Формальная ⚠️ │ o-reply │ sed_no-reply_Уведомление о стату...
4 │ 2026-02-17 │ Формальная ⚠️ │ o-reply │ sed_no-reply_Уведомление о стату...
5 │ 2026-02-18 │ Формальная ⚠️ │ o-reply │ sed_no-reply_Уведомление о стату...
📊 Итого по органу: 5 писем | Ответов: 5 (100%)
────────────────────────────────────────────────
**📮 Почта России**
────────────────────────────────────────────────
№ │ Дата │ Статус │ Вх. № │ Тема
────┼────────────┼───────────────┼────────────────────┼───────────────────────────────
1 │ 2026-01-30 │ ⏳ Нет ответа │ otification │ Письмо из Ульяновска
2 │ 2026-01-31 │ ⏳ Нет ответа │ otification │ Письмо из Ульяновска
3 │ 2026-02-02 │ ⏳ Нет ответа │ otification │ Письмо из Ульяновска
4 │ 2026-02-02 │ ⏳ Нет ответа │ otification │ Предварительная запись в ОПС на ...
5 │ 2026-02-27 │ ⏳ Нет ответа │ otification │ Отправление EMS из Ульяновска
6 │ 2026-03-02 │ ⏳ Нет ответа │ otification │ Отправление EMS из Ульяновска
7 │ 2026-03-02 │ ⏳ Нет ответа │ otification │ Письмо из Ульяновска
8 │ 2026-03-03 │ ⏳ Нет ответа │ otification │ Мелкий пакет из Китая
9 │ 2026-03-03 │ ⏳ Нет ответа │ otification │ Письмо из Ульяновска
10 │ 2026-03-06 │ ⏳ Нет ответа │ otification │ Мелкий пакет из Китая
11 │ 2026-03-17 │ ⏳ Нет ответа │ otification │ Письмо из Ульяновска
12 │ 2026-03-18 │ ⏳ Нет ответа │ otification │ Письмо из Ульяновска
13 │ 2026-03-18 │ ⏳ Нет ответа │ otification │ Электронное извещение
14 │ 2026-03-19 │ ⏳ Нет ответа │ otification │ Письмо из Ульяновска
15 │ 2026-03-20 │ ⏳ Нет ответа │ otification │ Письмо из Ульяновска
16 │ 2026-03-21 │ ⏳ Нет ответа │ otification │ Письмо из Ульяновска
17 │ 2026-03-22 │ ⏳ Нет ответа │ otification │ Письмо из Ульяновска
📊 Итого по органу: 17 писем | Ответов: 0 (0%)
================================================
📈 **СВОДНАЯ СТАТИСТИКА**
================================================
✉️ **Всего отправлено писем:** 331
✅ **Получено ответов:** 188 (57%)
⏳ **Без ответа:** 143 (43%)
📊 **КАЧЕСТВО ОТВЕТОВ:**
⚠️ Формальные отписки: 187 (99%)
✅ Ответы по существу: 1 (1%)
🎯 **ВЫВОД:**
⚠️ Преобладают формальные отписки. Требуется:
• Повторные обращения с требованием ответа по существу
• Жалобы в вышестоящие органы
• Обращение в прокуратуру на бездействие
================================================
🕐 Отчёт сформирован: 18:48 12.04.2026
================================================

112
report_table.txt Normal file
View file

@ -0,0 +1,112 @@
📊 **ОТЧЁТ ПО ПЕРЕПИСКЕ С ОРГАНАМИ**
📅 Дата формирования: 12.04.2026
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📮 **ПО ОРГАНАМ:**
**Госуслуги**
├─ Писем: 177
├─ Ответов: 98 (55%)
├─ #175 | 2026-03-27 | ✅ Ответ → Формальная отписка ⚠ [Вх.№ 20260100104989]
│ 📝 Доставлено информационное сообщение_ «Размеще...
├─ #176 | 2026-03-31 | ⏳ Нет ответа [Вх.№ o-reply]
│ 📝 Электронное заказное письмо...
├─ #177 | 2026-04-01 | ⏳ Нет ответа [Вх.№ o-reply]
│ 📝 Вы авторизовались, используя учётные данные Г...
└─ ... и ещё 174 писем
**УЛГСС (Ульяновск)**
├─ Писем: 33
├─ Ответов: 28 (85%)
├─ #31 | 2026-02-02 | ✅ Ответ → Формальная отписка ⚠ [Вх.№ 217]
│ 📝 ВОЗРАЖЕНИЕ на ответ № 217 от 28.01.2026 г....
├─ #32 | 2026-02-24 | ✅ Ответ → Формальная отписка ⚠ [Вх.№ fo]
│ 📝 Уведомление о визите...
├─ #33 | 2026-03-10 | ✅ Ответ → Формальная отписка ⚠ [Вх.№ fo]
│ 📝 ТРЕБОВАНИЕ В АДРЕС ДИРЕКТОРА ООО «УО ЖСС»...
└─ ... и ещё 30 писем
**УЛГКХ (Ульяновск)**
├─ Писем: 29
├─ Ответов: 28 (97%)
├─ #27 | 2026-02-24 | ✅ Ответ → Формальная отписка ⚠ [Вх.№ fo]
│ 📝 Fwd_ Уведомление о визите...
├─ #28 | 2026-02-25 | ✅ Ответ → Формальная отписка ⚠ [Вх.№ fo]
│ 📝 Дополнительный ответ...
├─ #29 | 2026-03-12 | ✅ Ответ → Формальная отписка ⚠ [Вх.№ fo]
│ 📝 Fwd_ ТРЕБОВАНИЕ В АДРЕС ДИРЕКТОРА ООО «УО ЖСС...
└─ ... и ещё 26 писем
**Роспотребнадзор**
├─ Писем: 9
├─ Ответов: 5 (56%)
├─ #7 | 2026-02-17 | ⏳ Нет ответа [Вх.№ 73-00-04/46-991-2026]
│ 📝 Ответ № 73-00-04_46-991-2026 от 17.02.2026 на...
├─ #8 | 2026-02-24 | ⏳ Нет ответа [Вх.№ 73-00-04/46-1135-2026]
│ 📝 Ответ № 73-00-04_46-1135-2026 от 24.02.2026 н...
├─ #9 | 2026-03-17 | ⏳ Нет ответа [Вх.№ 73-00-04/46-1692-2026]
│ 📝 Ответ № 73-00-04_46-1692-2026 от 17.03.2026 н...
└─ ... и ещё 6 писем
**Почта России (mailop)**
├─ Писем: 9
├─ Ответов: 9 (100%)
├─ #7 | 2026-02-17 | ✅ Ответ → Формальная отписка ⚠ [Вх.№ /pdf]
│ 📝 Уведомление по обращению...
├─ #8 | 2026-02-19 | ✅ Ответ → Формальная отписка ⚠ [Вх.№ /pdf]
│ 📝 Уведомление по обращению...
├─ #9 | 2026-02-24 | ✅ Ответ → Формальная отписка ⚠ [Вх.№ /pdf]
│ 📝 Ответ Тырину А.А....
└─ ... и ещё 6 писем
**Правительство РФ**
├─ Писем: 52
├─ Ответов: 11 (21%)
├─ #50 | 2026-03-20 | ✅ Ответ → Формальная отписка ⚠ [Вх.№ 1925-01/73]
│ 📝 №1925-01_73 от 20.03.2026_ О рассмотрении обр...
├─ #51 | 2026-03-23 | ✅ Ответ → Формальная отписка ⚠ [Вх.№ o-reply]
│ 📝 Роскомнадзор предлагает оценить качество рабо...
├─ #52 | 2026-04-03 | ⏳ Нет ответа [Вх.№ 73-ИОГВ-18/3993исх]
│ 📝 Исходящий N 73-ИОГВ-18_3993исх от 03.04.2026 ...
└─ ... и ещё 49 писем
**МВД России**
├─ Писем: 5
├─ Ответов: 5 (100%)
├─ #3 | 2026-02-06 | ✅ Ответ → Формальная отписка ⚠ [Вх.№ o-reply]
│ 📝 sed_no-reply_Уведомление о статусе обращения ...
├─ #4 | 2026-02-17 | ✅ Ответ → Формальная отписка ⚠ [Вх.№ o-reply]
│ 📝 sed_no-reply_Уведомление о статусе обращения ...
├─ #5 | 2026-02-18 | ✅ Ответ → Формальная отписка ⚠ [Вх.№ o-reply]
│ 📝 sed_no-reply_Уведомление о статусе обращения ...
└─ ... и ещё 2 писем
**Почта России**
├─ Писем: 17
├─ Ответов: 1 (6%)
├─ #15 | 2026-03-20 | ⏳ Нет ответа [Вх.№ otification]
│ 📝 Письмо из Ульяновска...
├─ #16 | 2026-03-21 | ⏳ Нет ответа [Вх.№ otification]
│ 📝 Письмо из Ульяновска...
├─ #17 | 2026-03-22 | ⏳ Нет ответа [Вх.№ otification]
│ 📝 Письмо из Ульяновска...
└─ ... и ещё 14 писем
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📈 **ИТОГО:**
✉️ Всего отправлено: **331**
✅ Получено ответов: **185** (56%)
⏳ Без ответа: **146**
📊 **КАЧЕСТВО ОТВЕТОВ:**
⚠️ Формальные отписки: **181** (98%)
✅ Ответы по существу: **4** (2%)
🎯 **ВЫВОД:**
Преобладают **формальные отписки**. Требуется escalation. ⚠️
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🕐 Сформировано: 18:46 12.04.2026