amoriai/lib/services/emailjs_service.dart

117 lines
3.2 KiB
Dart

import 'dart:convert';
import 'dart:math';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
/// Service for sending OTP emails via SMTP API
class EmailJSService {
// Gmail SMTP Configuration
static const String _senderEmail = 'erdiseptawahyupratamaggwp@gmail.com';
static const String _appPassword = 'bcwgpewcqxcyhszp';
static const String _apiUrl = 'https://freeemailapi.vercel.app/sendEmail/';
// Store OTP codes temporarily
static final Map<String, _OTPData> _otpStore = {};
static String? lastGeneratedOTP;
/// Generate a random 5-digit OTP
static String generateOTP() {
final random = Random();
return (10000 + random.nextInt(90000)).toString();
}
/// Send OTP to email
static Future<bool> sendOTP(String email) async {
try {
final otp = generateOTP();
final expiresAt = DateTime.now().add(const Duration(minutes: 5));
_otpStore[email] = _OTPData(otp: otp, expiresAt: expiresAt);
lastGeneratedOTP = otp;
debugPrint('📤 Sending OTP to $email...');
final response = await http.post(
Uri.parse(_apiUrl),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'fromEmail': _senderEmail,
'passkey': _appPassword,
'toEmail': email,
'title': 'Amori Assistant',
'subject': 'Kode Verifikasi OTP',
'body':
'Kode verifikasi Anda adalah: $otp\n\n'
'Kode ini berlaku selama 5 menit.\n'
'Jika Anda tidak meminta kode ini, abaikan email ini.',
}),
);
final data = jsonDecode(response.body);
final message = data['message']?.toString() ?? '';
debugPrint('📥 Email API Response: $message');
if (message == 'emailSendSuccess') {
debugPrint('✅ OTP sent successfully to $email');
return true;
} else {
debugPrint('❌ Failed to send OTP: $message');
return false;
}
} catch (e) {
debugPrint('❌ Error sending OTP: $e');
return false;
}
}
/// Verify OTP code
static bool verifyOTP(String email, String code) {
final otpData = _otpStore[email];
if (otpData == null) {
debugPrint('❌ No OTP found for $email');
return false;
}
if (DateTime.now().isAfter(otpData.expiresAt)) {
debugPrint('❌ OTP expired for $email');
_otpStore.remove(email);
return false;
}
if (otpData.otp != code) {
debugPrint(
'❌ Invalid OTP for $email (expected: ${otpData.otp}, got: $code)',
);
return false;
}
debugPrint('✅ OTP verified for $email');
_otpStore.remove(email);
return true;
}
/// Check if OTP exists and is valid (not expired)
static bool hasValidOTP(String email) {
final otpData = _otpStore[email];
if (otpData == null) return false;
return DateTime.now().isBefore(otpData.expiresAt);
}
/// Clear OTP for email
static void clearOTP(String email) {
_otpStore.remove(email);
}
/// Get last generated OTP (for dev mode display)
static String? getLastOTP() => lastGeneratedOTP;
}
class _OTPData {
final String otp;
final DateTime expiresAt;
_OTPData({required this.otp, required this.expiresAt});
}