04/13/2026 Fixed email ingres function

This commit is contained in:
2026-04-13 18:18:15 -04:00
parent 7f025c613f
commit cacc92636a
4 changed files with 257 additions and 59 deletions
+119 -1
View File
@@ -1434,4 +1434,122 @@ def settings():
branding_settings=branding_settings,
email_settings=email_settings,
current_tz=current_tz,
common_timezones=common_timezones)
common_timezones=common_timezones)
# ── Email Ingestion: Test Connection ─────────────────────────────────────────
@admin_bp.route('/settings/email-ingestion/test', methods=['POST'])
@login_required
@admin_required
def email_ingestion_test():
"""AJAX endpoint — attempt an IMAP login with the supplied credentials
and return a JSON result. The password field is optional: if left blank
the stored password is used so the admin does not have to re-enter it
just to run a connection test.
"""
from app.models import SystemSetting
import imaplib
host = request.form.get('host', '').strip()
port_str = request.form.get('port', '993').strip()
user = request.form.get('user', '').strip()
password = request.form.get('password', '').strip()
folder = request.form.get('folder', 'INBOX').strip()
# Fall back to the stored password if the admin left the field blank
if not password:
password = SystemSetting.get('email_ingestion_password', '')
if not host or not user or not password:
return jsonify(ok=False, message='Host, username, and password are required.')
try:
port = int(port_str)
except ValueError:
return jsonify(ok=False, message=f'Invalid port number: {port_str!r}')
try:
imap = imaplib.IMAP4_SSL(host, port)
imap.login(user, password)
# Verify the watch folder exists
quoted_folder = f'"{folder}"'
status, data = imap.select(quoted_folder, readonly=True)
if status != 'OK':
imap.logout()
return jsonify(
ok=False,
message=(
f'Login succeeded but folder {folder!r} was not found or '
f'is not accessible. Check the Watch Folder setting.'
)
)
# Count unseen messages for informational feedback
_, msg_data = imap.search(None, 'UNSEEN')
unseen = len(msg_data[0].split()) if msg_data and msg_data[0] else 0
imap.logout()
log_action(
current_user.id, 'email_ingestion_test', 'system_setting', None,
f'host={host} port={port} user={user} folder={folder} unseen={unseen}'
)
logger.info(
f'[ADMIN EMAIL INGEST] Connection test OK: host={host} user={user} '
f'folder={folder} unseen={unseen} by admin_id={current_user.id}'
)
return jsonify(
ok=True,
message=(
f'Connection successful. Folder {folder!r} is accessible '
f'({unseen} unseen message(s)).'
)
)
except imaplib.IMAP4.error as exc:
logger.warning(
f'[ADMIN EMAIL INGEST] Connection test failed: host={host} user={user} '
f'error={exc} by admin_id={current_user.id}'
)
return jsonify(ok=False, message=f'IMAP error: {exc}')
except OSError as exc:
logger.warning(
f'[ADMIN EMAIL INGEST] Connection test network error: host={host} '
f'port={port} error={exc} by admin_id={current_user.id}'
)
return jsonify(ok=False, message=f'Network error: {exc}')
except Exception as exc:
logger.error(
f'[ADMIN EMAIL INGEST] Connection test unexpected error: {exc}',
exc_info=True
)
return jsonify(ok=False, message=f'Unexpected error: {exc}')
# ── Email Ingestion: Run Now ──────────────────────────────────────────────────
@admin_bp.route('/settings/email-ingestion/run-now', methods=['POST'])
@login_required
@admin_required
def email_ingestion_run_now():
"""Trigger an immediate ingestion run outside the scheduler cycle.
Runs synchronously in the request (the job is fast for small mailboxes).
Returns JSON so the UI can surface the outcome without a full page reload.
"""
from app.models import SystemSetting
from app.services.email_ingestion_service import _run_ingestion
if SystemSetting.get('email_ingestion_enabled', '0') != '1':
return jsonify(ok=False, message='Email ingestion is currently disabled. Enable it first.')
log_action(
current_user.id, 'email_ingestion_run_now', 'system_setting', None,
f'manual run triggered by admin_id={current_user.id}'
)
logger.info(f'[ADMIN EMAIL INGEST] Manual run triggered by admin_id={current_user.id}')
try:
_run_ingestion(current_app._get_current_object())
return jsonify(ok=True, message='Ingestion run completed. Check the activity log for details.')
except Exception as exc:
logger.error(f'[ADMIN EMAIL INGEST] Manual run error: {exc}', exc_info=True)
return jsonify(ok=False, message=f'Run failed: {exc}')