Устранение неполадок
На этой странице описаны наиболее распространённые проблемы при работе с PRX-Email, а также их причины и решения.
Истёкший OAuth-токен
Симптомы: Операции завершаются с кодом ошибки Provider и сообщением об истёкших токенах.
Возможные причины:
- OAuth-токен доступа истёк, и провайдер обновления не настроен
- Переменная окружения
*_OAUTH_EXPIRES_ATсодержит устаревшую временную метку - Провайдер обновления возвращает ошибки
Решения:
- Проверьте временные метки истечения токенов:
echo $PRX_EMAIL_IMAP_OAUTH_EXPIRES_AT
echo $PRX_EMAIL_SMTP_OAUTH_EXPIRES_AT
# Должны быть Unix-timestamps в будущем- Перезагрузите токены из окружения вручную:
// Установить свежие токены
std::env::set_var("PRX_EMAIL_IMAP_OAUTH_TOKEN", "new-token");
std::env::set_var("PRX_EMAIL_SMTP_OAUTH_TOKEN", "new-token");
// Перезагрузить
plugin.reload_auth_from_env("PRX_EMAIL");- Реализуйте провайдер обновления для автоматического обновления токенов:
let plugin = EmailPlugin::new_with_config(repo, config)
.with_refresh_provider(Box::new(my_refresh_provider));- Повторно запустите Outlook bootstrap-скрипт для получения свежих токенов:
CLIENT_ID='...' TENANT='...' REDIRECT_URI='...' \
./scripts/outlook_oauth_bootstrap.shTIP
PRX-Email пытается обновить токены за 60 секунд до их истечения. Если ваши токены истекают быстрее интервала синхронизации, убедитесь, что провайдер обновления подключён.
Сбой синхронизации IMAP
Симптомы: sync() возвращает ошибку Network, или sync runner сообщает о неудачах.
Возможные причины:
- Неверное имя хоста или порт IMAP-сервера
- Проблемы сетевого подключения
- Сбой аутентификации (неверный пароль или истёкший OAuth-токен)
- Ограничение скорости IMAP-сервером
Решения:
- Проверьте подключение к IMAP-серверу:
openssl s_client -connect imap.example.com:993 -quiet- Проверьте конфигурацию транспорта:
// Убедиться, что хост и порт корректны
println!("IMAP host: {}", config.imap.host);
println!("IMAP port: {}", config.imap.port);- Проверьте режим аутентификации:
// Должен быть установлен ровно один
assert!(config.imap.auth.password.is_some() ^ config.imap.auth.oauth_token.is_some());- Проверьте состояние backoff sync runner. После повторных неудач планировщик применяет экспоненциальный backoff. Временно сбросьте, используя далёкое будущее в качестве
now_ts:
let report = plugin.run_sync_runner(&jobs, now + 86400, &config);- Проверьте структурированные логи для получения детальной информации об ошибке:
# Искать структурированные логи, связанные с синхронизацией
grep "prx_email.*sync" /path/to/logsСбой отправки SMTP
Симптомы: send() возвращает ApiResponse с ok: false и ошибкой Network или Provider.
Возможные причины:
- Неверное имя хоста или порт SMTP-сервера
- Сбой аутентификации
- Адрес получателя отклонён провайдером
- Превышение лимитов скорости или квоты отправки
Решения:
- Проверьте статус outbox:
let outbox = plugin.get_outbox(outbox_id)?;
if let Some(msg) = outbox {
println!("Status: {}", msg.status);
println!("Retries: {}", msg.retries);
println!("Last error: {:?}", msg.last_error);
println!("Next attempt: {}", msg.next_attempt_at);
}- Проверьте конфигурацию SMTP:
// Проверить режим аутентификации
println!("Auth: password={}, oauth={}",
config.smtp.auth.password.is_some(),
config.smtp.auth.oauth_token.is_some());Проверьте ошибки валидации. Send API отклоняет:
- Пустые
to,subjectилиbody_text - Отключённый флаг функции
email_send - Недействительные адреса электронной почты
- Пустые
Тестируйте с симулированным сбоем для проверки обработки ошибок:
use prx_email::plugin::SendFailureMode;
let response = plugin.send(SendEmailRequest {
// ... поля ...
failure_mode: Some(SendFailureMode::Network), // Симулировать сбой
});Outbox застрял в состоянии "sending"
Симптомы: Outbox-записи имеют status = 'sending', но процесс аварийно завершился до финализации.
Причина: Процесс завершился после взятия outbox-записи, но до финализации её как sent или failed.
Решение: Вручную восстановите застрявшие записи через SQL:
-- Определить застрявшие строки (порог: 15 минут)
SELECT id, account_id, updated_at
FROM outbox
WHERE status = 'sending' AND updated_at < strftime('%s','now') - 900;
-- Восстановить в failed и запланировать повтор
UPDATE outbox
SET status = 'failed',
last_error = 'recovered_from_stuck_sending',
next_attempt_at = strftime('%s','now') + 30,
updated_at = strftime('%s','now')
WHERE status = 'sending' AND updated_at < strftime('%s','now') - 900;Вложение отклонено
Симптомы: Отправка завершается с "attachment exceeds size limit" или "attachment content type is not allowed".
Решения:
- Проверьте политику вложений:
let policy = &config.attachment_policy;
println!("Max size: {} bytes", policy.max_size_bytes);
println!("Allowed types: {:?}", policy.allowed_content_types);Проверьте размер файла — он должен быть в пределах лимита (по умолчанию: 25 МиБ).
Добавьте MIME-тип в список разрешённых, если он безопасен:
policy.allowed_content_types.insert("application/vnd.ms-excel".to_string());- Для вложений по пути убедитесь, что путь к файлу находится в пределах настроенного корня хранилища вложений. Пути с
../или симлинки, разрешающиеся за пределами корня, отклоняются.
Ошибка отключённой функции
Симптомы: Операции возвращают код ошибки FeatureDisabled.
Причина: Флаг функции для запрошенной операции не включён для аккаунта.
Решение:
// Проверить текущее состояние
let enabled = plugin.is_feature_enabled(account_id, "email_send")?;
println!("email_send enabled: {}", enabled);
// Включить функцию
plugin.set_account_feature(account_id, "email_send", true, now)?;
// Или установить глобальное значение по умолчанию
plugin.set_feature_default("email_send", true, now)?;Ошибки SQLite-базы данных
Симптомы: Операции завершаются с кодом ошибки Storage.
Возможные причины:
- Файл базы данных заблокирован другим процессом
- Диск заполнен
- Файл базы данных повреждён
- Миграции не выполнены
Решения:
- Выполните миграции:
let store = EmailStore::open("./email.db")?;
store.migrate()?;- Проверьте заблокированную базу данных. Одновременно может быть активно только одно подключение с записью. Увеличьте busy timeout:
let config = StoreConfig {
busy_timeout_ms: 30_000, // 30 секунд
..StoreConfig::default()
};- Проверьте место на диске:
df -h .- Восстановите или пересоздайте если база данных повреждена:
# Резервная копия существующей базы данных
cp email.db email.db.bak
# Проверить целостность
sqlite3 email.db "PRAGMA integrity_check;"
# Если повреждена, экспортируйте и импортируйте
sqlite3 email.db ".dump" | sqlite3 email_new.dbПроблемы WASM-плагинов
Ошибка Network Guard
Симптомы: WASM-операции с электронной почтой возвращают ошибку EMAIL_NETWORK_GUARD.
Причина: Переключатель безопасности сети не включён.
Решение:
export PRX_EMAIL_ENABLE_REAL_NETWORK=1Хост-возможность недоступна
Симптомы: Операции возвращают EMAIL_HOST_CAPABILITY_UNAVAILABLE.
Причина: Хост-среда выполнения не предоставляет email-возможность. Это происходит при выполнении за пределами WASM-контекста.
Решение: Убедитесь, что PRX-среда настроена для предоставления email host-calls плагину.
Sync Runner продолжает пропускать задачи
Симптомы: Sync runner сообщает attempted: 0, хотя задачи настроены.
Причина: Все задачи находятся в backoff из-за предыдущих неудач.
Решения:
Проверьте состояние backoff неудач, изучив структурированные логи.
Проверьте сетевую доступность и аутентификацию IMAP перед повторным запуском.
Сбросьте backoff, используя далёкую временную метку:
let report = plugin.run_sync_runner(&jobs, now + 86400, &default_config);Высокий процент неудач отправки
Симптомы: Метрики показывают высокое количество send_failures.
Решения:
- Изучите структурированные логи, отфильтрованные по
run_idиerror_code:
grep "prx_email.*send_failed" /path/to/logsПроверьте режим аутентификации SMTP. Убедитесь, что установлен ровно один из password или oauth_token.
Проверьте доступность провайдера перед широким развёртыванием.
Проверьте метрики:
let metrics = plugin.metrics_snapshot();
println!("Send failures: {}", metrics.send_failures);
println!("Retry count: {}", metrics.retry_count);Получение помощи
Если ни одно из вышеперечисленных решений не помогает:
- Проверьте существующие issues: github.com/openprx/prx_email/issues
- Создайте новый issue с:
- Версией PRX-Email (проверьте
Cargo.toml) - Версией Rust toolchain (
rustc --version) - Соответствующим выводом структурированных логов
- Шагами воспроизведения
- Версией PRX-Email (проверьте
Следующие шаги
- Справочник конфигурации — обзор всех настроек
- OAuth-аутентификация — решение проблем, специфичных для OAuth
- SQLite-хранение — обслуживание и восстановление базы данных