$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); } } } }