diff --git a/frontend/src/components/MailDetail.jsx b/frontend/src/components/MailDetail.jsx index 59e5c10..562ce7f 100644 --- a/frontend/src/components/MailDetail.jsx +++ b/frontend/src/components/MailDetail.jsx @@ -2,7 +2,7 @@ * 메일 상세 보기 컴포넌트 * 선택된 메일의 내용, 첨부파일, 액션 버튼 표시 */ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import { useNavigate } from 'react-router-dom'; import { useMail } from '../context/MailContext'; import { Trash2, Printer, Star, Reply, Forward, Mail as MailIcon, MailOpen, Archive, Paperclip, Download, FileText, Image, File, Edit, AlertOctagon, Languages, Sparkles } from 'lucide-react'; @@ -15,6 +15,103 @@ import { encodeEmailId } from '../utils/emailIdEncoder'; import { HighlightText } from '../utils/highlightText'; import ConfirmDialog from './ConfirmDialog'; +/** + * 이메일 HTML을 iframe 안에서 렌더링하는 컴포넌트 (CSS 격리) + */ +const EmailIframe = ({ htmlContent }) => { + const iframeRef = useRef(null); + + useEffect(() => { + if (iframeRef.current && htmlContent) { + const doc = iframeRef.current.contentDocument; + if (doc) { + doc.open(); + doc.write(` + + + + + + + + ${htmlContent} + + `); + doc.close(); + + // iframe 높이 자동 조절 - 실제 콘텐츠 높이 측정 + const resizeIframe = () => { + if (iframeRef.current && doc.body) { + // 모든 자식 요소의 실제 위치를 기반으로 높이 계산 + const children = doc.body.children; + let maxBottom = 0; + + for (let child of children) { + const rect = child.getBoundingClientRect(); + const bottom = rect.top + rect.height; + if (bottom > maxBottom) { + maxBottom = bottom; + } + } + + // 최소 100px, 최대 계산된 높이 + 여유 20px + const height = Math.max(maxBottom + 20, 100); + iframeRef.current.style.height = height + 'px'; + } + }; + + // 이미지 로드 후 재조정 + const images = doc.images; + let loadedCount = 0; + const totalImages = images.length; + + if (totalImages === 0) { + resizeIframe(); + } else { + for (let img of images) { + img.onload = img.onerror = () => { + loadedCount++; + resizeIframe(); + }; + } + } + + // 초기 크기 설정 + 지연 재조정 + setTimeout(resizeIframe, 50); + setTimeout(resizeIframe, 200); + setTimeout(resizeIframe, 500); + } + } + }, [htmlContent]); + + return ( +