isSMTP(); $mail->Host = getenv('SMTP_HOST'); $mail->SMTPAuth = true; $mail->Port = (int) getenv('SMTP_PORT'); $mail->SMTPSecure = $mail->Port === 465 ? PHPMailer::ENCRYPTION_SMTPS : PHPMailer::ENCRYPTION_STARTTLS; $mail->Username = getenv('SMTP_USERNAME'); $mail->Password = getenv('SMTP_PASSWORD'); $mail->SMTPOptions = [ 'ssl' => [ 'cafile' => '/etc/ssl/certs/ca-certificates.crt', 'verify_peer' => true, 'verify_peer_name' => true, ], ]; $mail->setFrom(getenv('SMTP_FROM_EMAIL'), getenv('SMTP_FROM_NAME')); $mail->isHTML(true); return $mail; } function sendEmailVerificationEmail(string $toEmail, string $username, string $verifyLink): bool { try { $mail = configureAppMailer(); $mail->addAddress($toEmail, $username); $mail->Subject = 'Verify your email to start creating critters'; $safeUsername = htmlspecialchars($username, ENT_QUOTES, 'UTF-8'); $safeVerifyLink = htmlspecialchars($verifyLink, ENT_QUOTES, 'UTF-8'); $mail->Body = '

Welcome, ' . $safeUsername . '! 🐾

Your OurApp account has been created. Verify your email to unlock your free credits and start creating unique, AI-generated critters — pick an adjective, animal, action, and location, and watch your imagination come to life.

Verify Email

If you didn’t create this account, you can safely ignore this email.

'; $mail->AltBody = "Welcome, {$username}!\n\nYour OurApp account has been created. Verify your email to unlock your free credits and start creating unique, AI-generated critters:\n\n{$verifyLink}\n\nIf you didn't create this account, you can safely ignore this email."; $mail->send(); return true; } catch (PHPMailerException $e) { error_log('Email verification email failed: ' . (isset($mail) ? $mail->ErrorInfo : $e->getMessage())); return false; } } function sendPasswordResetEmail(string $toEmail, string $username, string $resetLink): bool { try { $mail = configureAppMailer(); $mail->addAddress($toEmail, $username); $mail->Subject = 'Reset your OurApp password'; $safeUsername = htmlspecialchars($username, ENT_QUOTES, 'UTF-8'); $safeResetLink = htmlspecialchars($resetLink, ENT_QUOTES, 'UTF-8'); $mail->Body = '

Reset your password

Hi ' . $safeUsername . ', we received a request to reset your OurApp password. Click the button below to choose a new one. This link expires in 20 minutes.

Reset Password

If you didn’t request a password reset, you can safely ignore this email — your password will not be changed.

'; $mail->AltBody = "Hi {$username},\n\nWe received a request to reset your OurApp password. Visit the link below to choose a new one. This link expires in 20 minutes.\n\n{$resetLink}\n\nIf you didn't request a password reset, you can safely ignore this email."; $mail->send(); return true; } catch (PHPMailerException $e) { error_log('Password reset email failed: ' . (isset($mail) ? $mail->ErrorInfo : $e->getMessage())); return false; } }