Mengganti alamat email akun tidak boleh langsung dilakukan tanpa verifikasi, karena bisa disalahgunakan jika akun diretas. Solusinya adalah sistem 2-Step Email Change: perubahan email baru harus dikonfirmasi melalui tautan verifikasi yang dikirim ke email baru sebelum diterapkan, jadi ini adalah Sistem Konfirmasi Email Baru Sebelum Aktif.
Dengan sistem ini:
-
Email lama tetap aktif hingga proses konfirmasi selesai.
-
Pengguna diberi tahu lewat email lama dan diminta verifikasi di email baru.
-
Aman dari serangan pengambilalihan akun.
Tabel users (sama seperti sebelumnya, tambahkan dua kolom baru):
ALTER TABLE users ADD COLUMN new_email VARCHAR(255) NULL, ADD COLUMN email_token VARCHAR(255) NULL;
Langkah 1: Form Ganti Email
File: change_email.php
<form method="post" action="process_change_email.php">
<div class="form-group">
<label>Email Baru</label>
<input type="email" name="new_email" class="form-control" required>
</div>
<button type="submit" name="change_email" class="btn btn-primary">Ubah Email</button>
</form>
Langkah 2: Proses Kirim Token Verifikasi ke Email Baru
File: process_change_email.php
<?php
session_start();
require 'config.php';
require 'vendor/autoload.php';
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
if (isset($_POST['change_email'])) {
$user_id = $_SESSION['user_id'];
$new_email = trim($_POST['new_email']);
// Ambil email lama dan username
$stmt = $conn->prepare("SELECT email, username FROM users WHERE id = ?");
$stmt->bind_param("i", $user_id);
$stmt->execute();
$stmt->bind_result($old_email, $username);
$stmt->fetch();
$stmt->close();
// Buat token unik untuk verifikasi
$token = bin2hex(random_bytes(32));
// Simpan email baru & token ke database
$stmt = $conn->prepare("UPDATE users SET new_email = ?, email_token = ? WHERE id = ?");
$stmt->bind_param("ssi", $new_email, $token, $user_id);
$stmt->execute();
$stmt->close();
// Kirim notifikasi ke email lama
sendOldEmailAlert($old_email, $username, $new_email);
// Kirim email konfirmasi ke email baru
sendVerificationToNewEmail($new_email, $username, $token);
echo "<script>alert('Kami telah mengirim link konfirmasi ke email baru Anda.'); window.location='profile.php';</script>";
}
function sendVerificationToNewEmail($to, $username, $token) {
$verifyLink = "https://yourdomain.com/verify_new_email.php?token=$token";
$mail = new PHPMailer(true);
try {
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->Username = 'your_email@gmail.com';
$mail->Password = 'your_app_password';
$mail->SMTPSecure = 'tls';
$mail->Port = 587;
$mail->setFrom('your_email@gmail.com', 'Account Verification');
$mail->addAddress($to);
$mail->isHTML(true);
$mail->Subject = "Verifikasi Email Baru Anda";
$mail->Body = "
<h3>Hai, $username </h3>
<p>Kami menerima permintaan untuk mengubah alamat email Anda.</p>
<p>Untuk mengonfirmasi, klik tautan di bawah ini:</p>
<p><a href='$verifyLink' target='_blank'>$verifyLink</a></p>
<p>Jika Anda tidak meminta perubahan ini, abaikan email ini.</p>
<hr><small>Pesan ini dikirim otomatis oleh sistem keamanan akun.</small>
";
$mail->send();
} catch (Exception $e) {
error_log("Gagal mengirim email verifikasi: {$mail->ErrorInfo}");
}
}
function sendOldEmailAlert($to, $username, $new_email) {
$mail = new PHPMailer(true);
try {
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->Username = 'your_email@gmail.com';
$mail->Password = 'your_app_password';
$mail->SMTPSecure = 'tls';
$mail->Port = 587;
$mail->setFrom('your_email@gmail.com', 'Security Alert');
$mail->addAddress($to);
$mail->isHTML(true);
$mail->Subject = "Pemberitahuan: Permintaan Ganti Email";
$mail->Body = "
<h3>Hai, $username</h3>
<p>Ada permintaan untuk mengganti email Anda menjadi <b>$new_email</b>.</p>
<p>Email lama Anda masih aktif sampai proses konfirmasi selesai.</p>
<hr><small>Jika Anda tidak meminta ini, segera ubah password Anda.</small>
";
$mail->send();
} catch (Exception $e) {
error_log("Gagal kirim alert: {$mail->ErrorInfo}");
}
}
?>
Langkah 3: Verifikasi Token Email Baru
File: verify_new_email.php
<?php
require 'config.php';
if (isset($_GET['token'])) {
$token = $_GET['token'];
// Cek token valid
$stmt = $conn->prepare("SELECT id, new_email FROM users WHERE email_token = ?");
$stmt->bind_param("s", $token);
$stmt->execute();
$stmt->bind_result($user_id, $new_email);
$stmt->fetch();
$stmt->close();
if ($user_id && $new_email) {
// Terapkan email baru & hapus token
$stmt = $conn->prepare("UPDATE users SET email = ?, new_email = NULL, email_token = NULL WHERE id = ?");
$stmt->bind_param("si", $new_email, $user_id);
$stmt->execute();
$stmt->close();
echo "<h3>Email baru berhasil dikonfirmasi ✅</h3>";
} else {
echo "<h3>Token tidak valid atau sudah digunakan ❌</h3>";
}
}
?>
Alur Lengkap Sistem
-
Pengguna mengisi form email baru.
-
Sistem:
-
Menyimpan
new_emaildanemail_token. -
Mengirim email verifikasi ke email baru.
-
Mengirim notifikasi ke email lama.
-
-
Pengguna membuka link dari email baru → sistem mengganti
emailutama dan menghapusnew_email + token.
Keamanan Tambahan
-
Token sebaiknya kedaluwarsa dalam 30 menit – 1 jam.
-
Validasi format email dengan
filter_var($email, FILTER_VALIDATE_EMAIL) -
Gunakan
password_confirmsebelum perubahan email. -
Catat aktivitas di tabel
security_logs.
Kesimpulan
Dengan sistem 2-Step Email Change, aplikasi PHP kamu jadi jauh lebih aman. Pengguna tidak hanya mendapat notifikasi di email lama, tetapi juga harus mengonfirmasi email baru sebelum aktif. Ini mencegah banyak serangan takeover akun dan meningkatkan kepercayaan pengguna terhadap keamanan sistemmu.