Files
2026-06-11 18:47:38 +09:00

233 lines
9.6 KiB
PHP

<?php
if (!defined('_GNUBOARD_')) exit;
// PHPMailer 라이브러리 및 필요한 Manager 클래스들을 포함합니다.
require_once(G5_PHPMAILER_PATH . '/PHPMailerAutoload.php');
require_once(__DIR__ . '/SmtpConfigManager.php');
require_once(__DIR__ . '/TemplateManager.php');
require_once(__DIR__ . '/SendLogManager.php');
/**
* Class MailSender
* SMTP 설정과 템플릿을 사용하여 메일을 발송하고 로그를 기록하는 클래스
*/
class MailSender {
/**
* 지정된 템플릿으로 메일을 발송합니다.
* @param string $template_code 발송할 템플릿의 고유 코드
* @param string|array $to_email 수신자 이메일 주소 (문자열 또는 배열)
* @param array $vars 템플릿의 변수를 치환할 값 배열
* @param string|array $cc_email 참조 이메일 주소 (문자열 또는 배열)
* @param string|array $bcc_email 숨은 참조 이메일 주소 (문자열 또는 배열)
* @return bool 발송 성공 여부
*/
public function send($template_code, $to_email, $vars = [], $cc_email = [], $bcc_email = []) {
$logManager = new SendLogManager();
// 로그 기록을 위해 배열을 문자열로 변환
$to_email_log = is_array($to_email) ? implode(', ', $to_email) : $to_email;
$cc_email_log = is_array($cc_email) ? implode(', ', $cc_email) : $cc_email;
$bcc_email_log = is_array($bcc_email) ? implode(', ', $bcc_email) : $bcc_email;
$log_data = [
'to_email' => $to_email_log,
'cc_email' => $cc_email_log,
'bcc_email_log' => $bcc_email_log,
'subject' => '',
'body' => '',
'status' => 'fail', // 기본 상태를 '실패'로 설정
'error_msg' => '',
];
try {
// 1. 사용중인 SMTP 설정 가져오기
$smtpManager = new SmtpConfigManager();
$smtp_config = $smtpManager->getInUse();
if (!$smtp_config) {
throw new Exception('사용 가능한 SMTP 설정이 없습니다.');
}
// 2. 템플릿 정보 가져오기
$templateManager = new TemplateManager();
$template = $templateManager->getByCode($template_code);
if (!$template) {
throw new Exception("템플릿 코드 '{$template_code}'를 찾을 수 없습니다.");
}
if (!$template['is_use']) {
throw new Exception("템플릿 '{$template['title']}'은(는) 현재 사용 중지 상태입니다.");
}
// 3. 변수 치환
$subject = $template['title'];
$header = $template['header_html'];
$content = $template['content'];
$footer = $template['footer_html'];
// 템플릿에 저장된 기본값과 사용자 입력값을 병합 (사용자 입력값이 우선)
$default_vars = $templateManager->getVarsByTemplateId($template['id']);
$final_vars = array_merge($default_vars, $vars);
// 모든 변수를 제목, 헤더, 본문, 푸터에 적용
foreach ($final_vars as $key => $value) {
$search = '{' . $key . '}';
$subject = str_replace($search, $value, $subject);
$header = str_replace($search, $value, $header);
$content = str_replace($search, $value, $content);
$footer = str_replace($search, $value, $footer);
}
$full_html = $header . $content . $footer;
$log_data['subject'] = $subject;
$log_data['body'] = $full_html;
// 4. PHPMailer 설정 및 발송
$mail = new PHPMailer;
$mail->isSMTP();
$mail->CharSet = 'utf-8';
$mail->Host = $smtp_config['host'];
$mail->SMTPAuth = true;
$mail->Username = $smtp_config['username'];
$mail->Password = $smtp_config['password'];
$mail->SMTPSecure = $smtp_config['encryption'];
$mail->Port = (int)$smtp_config['port'];
$mail->setFrom($smtp_config['from_email'], get_text(htmlspecialchars_decode(stripslashes($smtp_config['from_name']))));
// 수신자 추가 (배열 또는 콤마 구분 문자열 지원)
$this->addAddresses($mail, $to_email, 'addAddress');
// 참조자 추가
$this->addAddresses($mail, $cc_email, 'addCC');
// 숨은 참조자 추가
$this->addAddresses($mail, $bcc_email, 'addBCC');
$mail->isHTML(true);
$mail->Subject = htmlspecialchars_decode(stripslashes(get_text($subject)));
$mail->Body = htmlspecialchars_decode(stripslashes($full_html));
if (!$mail->send()) {
throw new Exception('Mailer Error: ' . $mail->ErrorInfo);
}
// 성공 시 로그 데이터 업데이트
$log_data['status'] = 'success';
$log_data['error_msg'] = '';
} catch (Exception $e) {
// 실패 시 오류 메시지 기록
$log_data['error_msg'] = $e->getMessage();
} finally {
// 5. 성공/실패 여부에 관계없이 발송 로그 기록
$logManager->addLog($log_data);
}
return $log_data['status'] === 'success';
}
/**
* 템플릿을 사용하지 않고, 이미 완성된 제목과 본문으로 메일을 발송합니다. (재발송 기능용)
* @param string|array $to_email 수신자 이메일 주소
* @param string $subject 메일 제목
* @param string $body 메일 본문 (HTML)
* @param int|null $original_log_id 재발송의 대상이 되는 원본 로그 ID
* @param string|array $cc_email 참조 이메일
* @param string|array $bcc_email 숨은 참조 이메일
* @return bool 발송 성공 여부
*/
public function sendRaw($to_email, $subject, $body, $original_log_id = null, $cc_email = [], $bcc_email = []) {
$logManager = new SendLogManager();
$to_email_log = is_array($to_email) ? implode(', ', $to_email) : $to_email;
$cc_email_log = is_array($cc_email) ? implode(', ', $cc_email) : $cc_email;
$log_data = [
'to_email' => $to_email_log,
'cc_email' => $cc_email_log,
'subject' => $subject,
'body' => $body,
'status' => 'fail', // 기본 상태를 '실패'로 설정
'error_msg' => '',
'resend_of' => $original_log_id // 재발송 로그 ID 기록
];
try {
// 1. 사용중인 SMTP 설정 가져오기
$smtpManager = new SmtpConfigManager();
$smtp_config = $smtpManager->getInUse();
if (!$smtp_config) {
throw new Exception('사용 가능한 SMTP 설정이 없습니다.');
}
// 2. 변수 치환 과정은 생략
// 3. PHPMailer 설정 및 발송
$mail = new PHPMailer;
$mail->isSMTP();
$mail->CharSet = 'utf-8';
$mail->Host = $smtp_config['host'];
$mail->SMTPAuth = true;
$mail->Username = $smtp_config['username'];
$mail->Password = $smtp_config['password'];
$mail->SMTPSecure = $smtp_config['encryption'];
$mail->Port = (int)$smtp_config['port'];
// [보안/개선] 발신자 이름에 포함될 수 있는 HTML 태그를 제거합니다.
$from_name = get_text(htmlspecialchars_decode(stripslashes($smtp_config['from_name'])));
$mail->setFrom($smtp_config['from_email'], $from_name);
// 수신자, 참조, 숨은참조 추가
$this->addAddresses($mail, $to_email, 'addAddress');
$this->addAddresses($mail, $cc_email, 'addCC');
$this->addAddresses($mail, $bcc_email, 'addBCC');
$mail->isHTML(true);
// [보안/개선] 로그에 저장된 제목과 본문은 이미 완성된 상태이므로 불필요한 함수 적용을 최소화합니다.
$mail->Subject = htmlspecialchars_decode(stripslashes(get_text($subject)));
$mail->Body = htmlspecialchars_decode(stripslashes($body));
if (!$mail->send()) {
throw new Exception('Mailer Error: ' . $mail->ErrorInfo);
}
// 성공 시 로그 데이터 업데이트
$log_data['status'] = 'success';
$log_data['error_msg'] = '';
} catch (Exception $e) {
// 실패 시 오류 메시지 기록
$log_data['error_msg'] = $e->getMessage();
} finally {
// 4. 성공/실패 여부에 관계없이 발송 로그 기록
$logManager->addLog($log_data);
}
return $log_data['status'] === 'success';
}
/**
* 이메일 주소 목록을 PHPMailer 객체에 추가하는 헬퍼 메소드
* @param object $mail PHPMailer 객체
* @param string|array $addresses 이메일 주소 (문자열 또는 배열)
* @param string $method PHPMailer 메소드명 (addAddress, addCC, addBCC)
*/
private function addAddresses($mail, $addresses, $method) {
if (empty($addresses)) return;
if (!is_array($addresses)) {
// 콤마로 구분된 문자열인 경우 배열로 변환
$addresses = explode(',', $addresses);
}
foreach ($addresses as $email) {
$email = trim($email);
if (!empty($email)) {
// $mail->$method($email) 형태로 호출
$mail->$method($email);
}
}
}
}