04/13/2026 Fixed email ingres function
This commit is contained in:
+119
-1
@@ -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}')
|
||||
|
||||
Reference in New Issue
Block a user