fix: distinguish email service errors and validate send receipts
This commit is contained in:
@@ -1,11 +1,16 @@
|
||||
import {emailConfiguration,sendEmailTest} from '../../services/emailNotifications';
|
||||
import {DeliveryQueue} from './DeliveryQueue';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { useApp } from '../../context/AppContext';
|
||||
import { Smartphone, Wifi, WifiOff, Download, Bell, CheckCircle2, Moon, Mail, Send } from 'lucide-react';
|
||||
import { getToken } from '../../services/auth';
|
||||
import { NotifySubscriptions } from './NotifySubscriptions';
|
||||
|
||||
export const PwaSettings = () => {
|
||||
const {authUser}=useApp();
|
||||
return <PwaPanel key={`${authUser?.email}:${getToken()}`}/>;
|
||||
};
|
||||
const PwaPanel = () => {
|
||||
const { userProfile, authUser, tenders, reminderSettings, saveReminderSettings, reminderSaving, reminderError, requestPushPermission, notify, isQuietNow } = useApp();
|
||||
// Gerçek Cache API sayımı — sahte "102 ihale önbellekte" yerine
|
||||
const [onbellekSayisi, setOnbellekSayisi] = useState(null);
|
||||
@@ -37,35 +42,25 @@ export const PwaSettings = () => {
|
||||
const [emailCfg, setEmailCfg] = useState(null); // null=bilinmiyor, true/false
|
||||
const [emailSending, setEmailSending] = useState(false);
|
||||
const [emailResult, setEmailResult] = useState(null);
|
||||
useEffect(() => {
|
||||
fetch('/api/notify/email/config')
|
||||
.then((r) => r.json())
|
||||
.then((d) => setEmailCfg(Boolean(d.configured)))
|
||||
.catch(() => setEmailCfg(false));
|
||||
}, []);
|
||||
const [emailConfigError,setEmailConfigError]=useState(null),[emailConfigAttempt,setEmailConfigAttempt]=useState(0);
|
||||
const alive=useRef(true),sendingLock=useRef(false),sendLifetime=useRef(new AbortController());
|
||||
useEffect(()=>{alive.current=true;sendLifetime.current=new AbortController();return()=>{alive.current=false;sendLifetime.current.abort();};},[]);
|
||||
useEffect(()=>{
|
||||
const controller=new AbortController();
|
||||
setEmailCfg(null);setEmailConfigError(null);
|
||||
emailConfiguration({signal:controller.signal}).then(data=>{if(!controller.signal.aborted)setEmailCfg(data.configured);})
|
||||
.catch(error=>{if(!controller.signal.aborted)setEmailConfigError(error.message);});
|
||||
return()=>controller.abort();
|
||||
},[emailConfigAttempt]);
|
||||
|
||||
const sendTestEmail = async () => {
|
||||
setEmailSending(true);
|
||||
setEmailResult(null);
|
||||
const sendTestEmail=async()=>{
|
||||
if(sendingLock.current || emailCfg!==true)return;
|
||||
sendingLock.current=true;setEmailSending(true);setEmailResult(null);
|
||||
try {
|
||||
const yeniler = tenders.filter((t) => t.isYeni).slice(0, 15);
|
||||
const res = await fetch('/api/notify/email/test', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${getToken()}` },
|
||||
body: JSON.stringify({ subject: 'İhaleist — bildirim testi', tenders: yeniler }),
|
||||
});
|
||||
const data = await res.json();
|
||||
if (data.success) {
|
||||
setEmailResult({ ok: true, msg: `E-posta gönderildi → ${data.to}` });
|
||||
notify('E-posta gönderildi', `Test e-postası ${data.to} adresine iletildi.`);
|
||||
} else {
|
||||
setEmailResult({ ok: false, msg: data.error || 'Gönderilemedi' });
|
||||
}
|
||||
} catch (e) {
|
||||
setEmailResult({ ok: false, msg: e.message });
|
||||
} finally {
|
||||
setEmailSending(false);
|
||||
}
|
||||
const data=await sendEmailTest(tenders.filter(t=>t.isYeni).slice(0,15),{signal:sendLifetime.current.signal});
|
||||
if(alive.current)setEmailResult({ok:true,msg:`E-posta sağlayıcısı gönderimi kabul etti → ${data.to}. Posta kutusuna teslim ayrıca doğrulanmalıdır.`});
|
||||
}catch(error){if(alive.current)setEmailResult({ok:false,msg:error.message});}
|
||||
finally{sendingLock.current=false;if(alive.current)setEmailSending(false);}
|
||||
};
|
||||
|
||||
const handleEnablePush = async () => {
|
||||
@@ -227,30 +222,32 @@ export const PwaSettings = () => {
|
||||
<span className={`font-extrabold text-[10px] px-2 py-0.5 rounded-full ${
|
||||
emailCfg === true ? 'bg-emerald-100 text-emerald-800' : emailCfg === false ? 'bg-amber-100 text-amber-800' : 'bg-slate-100 text-slate-600'
|
||||
}`}>
|
||||
{emailCfg === true ? 'Aktif (Resend)' : emailCfg === false ? 'Yapılandırılmadı' : 'Kontrol ediliyor…'}
|
||||
{emailConfigError ? 'Durum alınamadı' : emailCfg === true ? 'Yapılandırıldı (Resend)' : emailCfg === false ? 'Yapılandırılmadı' : 'Kontrol ediliyor…'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-slate-600 leading-relaxed">
|
||||
{emailCfg === false
|
||||
? 'E-posta göndermek için sunucuya RESEND_API_KEY ekleyin (Coolify → Environment). Ayrıca gönderen domainini Resend’de DNS ile doğrulayın.'
|
||||
? 'E-posta hizmeti henüz etkinleştirilmedi. Kurulum için yöneticinizle görüşün.'
|
||||
: 'Takip kriterlerinize uyan ihaleler, hesabınızın e-posta adresine özet olarak gönderilir. Aşağıdan kendinize test gönderebilirsiniz.'}
|
||||
</p>
|
||||
|
||||
{emailConfigError&&<p role="alert" className="text-xs text-red-700">{emailConfigError}</p>}
|
||||
<button type="button" disabled={emailSending} onClick={()=>setEmailConfigAttempt(n=>n+1)} className="text-xs underline">E-posta durumunu yenile</button>
|
||||
<p className="text-xs text-slate-600">E-posta gönderimlerini aşağıdaki bildirim aboneliklerinden yönetin. Tarayıcı bildirim seçimi ve sessiz saatler e-posta aboneliklerini kapatmaz.</p>
|
||||
|
||||
<button
|
||||
onClick={sendTestEmail}
|
||||
disabled={emailSending || emailCfg !== true || !authUser}
|
||||
className="w-full bg-blue-600 hover:bg-blue-500 disabled:opacity-40 text-white font-bold text-xs py-2.5 rounded-xl flex items-center justify-center gap-2"
|
||||
title={!authUser ? 'Giriş yapın' : emailCfg !== true ? 'RESEND_API_KEY gerekli' : 'Kendinize test e-postası gönder'}
|
||||
title={!authUser ? 'Giriş yapın' : emailCfg !== true ? 'E-posta hizmetinin etkin olduğunu doğrulayın' : 'Kendinize test e-postası gönder'}
|
||||
>
|
||||
<Send className="w-3.5 h-3.5" />
|
||||
{emailSending ? 'Gönderiliyor…' : 'Kendime Test E-postası Gönder'}
|
||||
</button>
|
||||
|
||||
{emailResult && (
|
||||
<p className={`text-[11px] ${emailResult.ok ? 'text-emerald-600' : 'text-red-600'}`}>
|
||||
<p role={emailResult.ok ? 'status' : 'alert'} className={`text-[11px] ${emailResult.ok ? 'text-emerald-600' : 'text-red-600'}`}>
|
||||
{emailResult.ok ? '✓ ' : '⚠ '}{emailResult.msg}
|
||||
</p>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user