PHP로 메일을 발송할 때 스팸으로 분류되거나 발송이 실패하는 문제가 자주 발생합니다. 이런 문제들의 주요 원인과 해결책을 살펴보겠습니다.
문제: From 헤더가 없거나 잘못 설정되어 스팸으로 분류
해결책:
$headers = "From: noreply@yourdomain.com\r\n";
$headers .= "Reply-To: support@yourdomain.com\r\n";
$headers .= "Return-Path: noreply@yourdomain.com\r\n";
$headers .= "X-Mailer: PHP/" . phpversion();
mail($to, $subject, $message, $headers);
문제: HTML 형식 메일이 제대로 인식되지 않아 스팸 처리
해결책:
$headers = "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=UTF-8\r\n";
$headers .= "From: sender@yourdomain.com\r\n";
$htmlMessage = "
<html>
<head><title>제목</title></head>
<body>
<p>안녕하세요!</p>
</body>
</html>";
mail($to, $subject, $htmlMessage, $headers);
문제: 한 번에 많은 메일을 발송하여 서버에서 차단
해결책:
// 배치 발송으로 처리
$emails = ['user1@email.com', 'user2@email.com', 'user3@email.com'];
$batchSize = 10;
foreach (array_chunk($emails, $batchSize) as $batch) {
foreach ($batch as $email) {
mail($email, $subject, $message, $headers);
sleep(1); // 1초 대기
}
sleep(5); // 배치 간 5초 대기
}
문제: 도메인 인증 설정이 없어 스팸으로 분류
해결책:
// PHPMailer 라이브러리 사용 (DKIM 서명 지원)
use PHPMailer\PHPMailer\PHPMailer;
$mail = new PHPMailer();
$mail->isSMTP();
$mail->Host = 'smtp.yourdomain.com';
$mail->SMTPAuth = true;
$mail->Username = 'your-email@yourdomain.com';
$mail->Password = 'your-password';
// DKIM 설정
$mail->DKIM_domain = 'yourdomain.com';
$mail->DKIM_private = '/path/to/private.key';
$mail->DKIM_selector = 'phpmailer';
$mail->send();
문제: 수신거부 옵션이 없어 스팸으로 신고됨
해결책:
$unsubscribeLink = "https://yourdomain.com/unsubscribe.php?token=" . md5($email);
$message = "
메일 내용...
---
수신거부: {$unsubscribeLink}
";
$headers .= "List-Unsubscribe: <{$unsubscribeLink}>\r\n";
mail($to, $subject, $message, $headers);
문제: 동일 사용자에게 너무 자주 메일 발송하여 스팸 처리
해결책:
// 발송 이력 체크
function canSendEmail($email, $type = 'general') {
$lastSent = getLastSentTime($email, $type); // DB에서 조회
$minInterval = 3600; // 1시간
return (time() - $lastSent) > $minInterval;
}
if (canSendEmail($email, 'newsletter')) {
mail($email, $subject, $message, $headers);
updateLastSentTime($email, 'newsletter'); // DB 업데이트
}
문제: 잘못된 이메일로 발송하여 반송률 증가
해결책:
function isValidEmail($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
function isDomainValid($email) {
$domain = substr(strrchr($email, "@"), 1);
return checkdnsrr($domain, 'MX');
}
if (isValidEmail($email) && isDomainValid($email)) {
mail($email, $subject, $message, $headers);
}
문제: 일부 메일 클라이언트에서 제대로 표시되지 않음
해결책:
$boundary = uniqid('boundary_');
$headers = "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: multipart/alternative; boundary=\"{$boundary}\"\r\n";
$headers .= "From: sender@yourdomain.com\r\n";
$message = "
--{$boundary}
Content-Type: text/plain; charset=UTF-8
플레인 텍스트 버전
--{$boundary}
Content-Type: text/html; charset=UTF-8
<html><body><p>HTML 버전</p></body></html>
--{$boundary}--";
mail($to, $subject, $message, $headers);
문제: 발송 실패 시 재시도 로직 없음
해결책:
function sendEmailWithRetry($to, $subject, $message, $headers, $maxRetries = 3) {
for ($i = 0; $i < $maxRetries; $i++) {
if (mail($to, $subject, $message, $headers)) {
return true;
}
sleep(pow(2, $i)); // 지수 백오프
}
// 실패 로그 기록
error_log("메일 발송 실패: {$to}");
return false;
}