Files
API-KTA/app/Libraries/EmailService.php
2026-04-25 04:41:23 +07:00

423 lines
15 KiB
PHP

<?php
namespace App\Libraries;
use CodeIgniter\Config\Services;
class EmailService
{
protected $email;
public function __construct()
{
$emailConfig = new \Config\Email();
$this->email = Services::email($emailConfig);
}
/**
* Kirim OTP via Email
*
* @param string $toEmail Email tujuan
* @param string $otpCode Kode OTP
* @param string $userName Nama user
* @param string $pangkat Pangkat user
* @return array ['success' => bool, 'message' => string]
*/
public function sendOtpEmail($toEmail, $otpCode, $userName, $pangkat = '')
{
try {
$this->email->setFrom('prodevbackend587@gmail.com', 'E-Teguran Humanis Polda NTB');
$this->email->setTo($toEmail);
$this->email->setSubject('E-Teguran Humanis - Verifikasi OTP');
$message = $this->getOtpEmailTemplate($otpCode, $userName, $pangkat);
$this->email->setMessage($message);
$result = $this->email->send();
if ($result) {
// PATCH: Set SMTPConnect ke null agar tidak error di __destruct
$reflection = new \ReflectionProperty($this->email, 'SMTPConnect');
$reflection->setAccessible(true);
$reflection->setValue($this->email, null);
// Cleanup
$this->email->clear(true);
return [
'success' => true,
'message' => 'Email OTP berhasil dikirim'
];
} else {
log_message('error', 'Email send error: ' . $this->email->printDebugger(['headers']));
// PATCH: Set SMTPConnect ke null agar tidak error di __destruct
$reflection = new \ReflectionProperty($this->email, 'SMTPConnect');
$reflection->setAccessible(true);
$reflection->setValue($this->email, null);
// Cleanup
$this->email->clear(true);
return [
'success' => false,
'message' => 'Gagal mengirim email OTP'
];
}
} catch (\Exception $e) {
log_message('error', 'Email exception: ' . $e->getMessage());
// PATCH: Set SMTPConnect ke null agar tidak error di __destruct
try {
$reflection = new \ReflectionProperty($this->email, 'SMTPConnect');
$reflection->setAccessible(true);
$reflection->setValue($this->email, null);
$this->email->clear(true);
} catch (\Exception $cleanupEx) {
// Ignore cleanup errors
}
return [
'success' => false,
'message' => 'Terjadi kesalahan saat mengirim email: ' . $e->getMessage()
];
}
}
/**
* Template HTML untuk email OTP (sesuai desain aplikasi)
*/
private function getOtpEmailTemplate($otpCode, $userName, $pangkat = '')
{
$fullName = !empty($pangkat) ? "{$pangkat} {$userName}" : $userName;
return '<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>E-Teguran Humanis Polda NTB</title>
<!-- Gmail-Compatible Email Styling -->
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, Helvetica, sans-serif !important;
color: #374151 !important;
background-color: #f0f9ff !important;
line-height: 1.6 !important;
margin: 0 !important;
padding: 0 !important;
}
table {
border-collapse: collapse;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
}
.email-wrapper {
width: 100% !important;
background-color: #f0f9ff !important;
padding: 20px 0 !important;
}
.email-container {
width: 600px !important;
max-width: 600px !important;
margin: 0 auto !important;
background-color: #ffffff !important;
border-radius: 12px !important;
overflow: hidden;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.email-header {
background-color: #002A95 !important;
color: #ffffff !important;
padding: 30px 20px !important;
text-align: center !important;
}
.logo-container {
margin-bottom: 20px !important;
text-align: center !important;
}
.logo-container img {
width: 80px !important;
height: 80px !important;
border-radius: 50% !important;
background-color: #ffffff !important;
padding: 2px !important;
display: inline-block !important;
vertical-align: middle !important;
border: 1px solid rgba(255, 255, 255, 0.3) !important;
}
.email-header h1 {
font-size: 24px !important;
font-weight: bold !important;
margin: 15px 0 8px 0 !important;
color: #ffffff !important;
}
.email-header p {
font-size: 14px !important;
color: #ffffff !important;
opacity: 0.9;
margin: 0 !important;
}
.email-body {
padding: 30px 20px !important;
}
.welcome-message {
background-color: #f0f9ff !important;
border-left: 4px solid #002A95 !important;
padding: 20px !important;
border-radius: 6px !important;
margin-bottom: 25px !important;
}
.welcome-message h2 {
color: #0c4a6e !important;
font-size: 18px !important;
font-weight: bold !important;
margin-bottom: 10px !important;
}
.welcome-message p {
color: #075985 !important;
font-size: 14px !important;
line-height: 1.5 !important;
margin: 0 !important;
}
.credentials-container {
background-color: #ffffff !important;
border: 2px solid #e0f2fe !important;
border-radius: 8px !important;
padding: 25px 20px !important;
margin: 25px 0 !important;
text-align: center !important;
}
.credentials-title {
color: #0c4a6e !important;
font-size: 16px !important;
font-weight: bold !important;
margin-bottom: 20px !important;
text-align: center !important;
}
.otp-display {
background-color: #f8fafc !important;
border: 2px dashed #002A95 !important;
border-radius: 8px !important;
padding: 25px !important;
margin: 20px 0 !important;
text-align: center !important;
}
.otp-label {
font-weight: bold !important;
color: #475569 !important;
font-size: 12px !important;
text-transform: uppercase !important;
letter-spacing: 0.5px !important;
margin-bottom: 15px !important;
}
.otp-code {
font-weight: bold !important;
color: #ffffff !important;
font-size: 32px !important;
background-color: #002A95 !important;
padding: 15px 25px !important;
border-radius: 6px !important;
letter-spacing: 8px !important;
display: inline-block !important;
font-family: "Courier New", Courier, monospace !important;
}
.otp-validity {
color: #64748b !important;
font-size: 13px !important;
margin-top: 15px !important;
font-style: italic !important;
}
.security-notice {
background-color: #fef3c7 !important;
border-left: 4px solid #f59e0b !important;
padding: 18px !important;
border-radius: 6px !important;
margin: 25px 0 !important;
}
.security-notice h3 {
color: #92400e !important;
font-size: 14px !important;
font-weight: bold !important;
margin-bottom: 8px !important;
}
.security-notice ul {
margin: 10px 0 0 0 !important;
padding-left: 20px !important;
}
.security-notice li {
color: #b45309 !important;
font-size: 13px !important;
line-height: 1.6 !important;
margin-bottom: 5px !important;
}
.email-footer {
background-color: #1e293b !important;
color: #ffffff !important;
padding: 25px 20px !important;
text-align: center !important;
}
.footer-content {
max-width: 400px;
margin: 0 auto !important;
}
.footer-logo {
font-size: 16px !important;
font-weight: bold !important;
margin-bottom: 8px !important;
color: #ffffff !important;
}
.footer-address {
font-size: 12px !important;
color: #ffffff !important;
opacity: 0.8;
line-height: 1.4 !important;
margin-bottom: 15px !important;
}
.footer-divider {
width: 40px !important;
height: 2px !important;
background-color: #002A95 !important;
margin: 0 auto 15px auto !important;
}
.footer-note {
font-size: 11px !important;
color: #ffffff !important;
opacity: 0.7;
font-style: italic !important;
margin: 0 !important;
}
/* Mobile Responsive */
@media only screen and (max-width: 600px) {
.email-container {
width: 100% !important;
margin: 0 10px !important;
}
.email-header,
.email-body,
.email-footer {
padding: 20px 15px !important;
}
.email-header h1 {
font-size: 20px !important;
}
.credentials-container {
padding: 20px 15px !important;
}
.otp-code {
font-size: 28px !important;
padding: 12px 20px !important;
letter-spacing: 6px !important;
}
}
</style>
</head>
<body>
<div class="email-wrapper">
<table class="email-container" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td>
<!-- Header Section -->
<div class="email-header">
<div class="logo-container">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b4/Lambang_Polda_NTB.png/800px-Lambang_Polda_NTB.png"
alt="Logo Polri" style="width: 80px; height: 80px; border-radius: 50%; background-color: #ffffff; padding: 2px; display: inline-block; border: 1px solid rgba(255, 255, 255, 0.3);" />
</div>
<h1>E-Teguran Humanis</h1>
<p>Polda Nusa Tenggara Barat</p>
</div>
<!-- Body Section -->
<div class="email-body">
<div class="welcome-message">
<h2>Verifikasi Akun Anda</h2>
<p>Kepada Yth. <strong>' . htmlspecialchars($fullName) . '</strong>, kami telah menerima permintaan verifikasi akun Anda.</p>
</div>
<div class="credentials-container">
<h3 class="credentials-title">Kode Verifikasi OTP Anda</h3>
<div class="otp-display">
<div class="otp-label">Kode OTP</div>
<div class="otp-code">' . htmlspecialchars($otpCode) . '</div>
<div class="otp-validity">Kode ini berlaku selama 10 menit</div>
</div>
</div>
<div class="security-notice">
<h3>⚠️ Penting untuk Keamanan</h3>
<ul>
<li><strong>Jangan bagikan</strong> kode ini kepada siapa pun</li>
<li>Kode ini hanya berlaku untuk <strong>10 menit</strong></li>
<li>Jika Anda tidak melakukan permintaan ini, segera hubungi administrator sistem</li>
</ul>
</div>
</div>
<!-- Footer Section -->
<div class="email-footer">
<div class="footer-content">
<div class="footer-logo">E-Teguran Humanis</div>
<div class="footer-address">
Polda Nusa Tenggara Barat<br>
Jl. Langko No. 77, Taman Sari, Ampenan, Kota Mataram
</div>
<div class="footer-divider"></div>
<div class="footer-note">
Email ini dikirim secara otomatis, mohon tidak membalas email ini.
</div>
</div>
</div>
</td>
</tr>
</table>
</div>
</body>
</html>';
}
}