h[5SSKrSSKrSSKJr SSKJr SSKJr SSKJ r SSK J r SSK J r JrJr SSKrSSKrSSKrSSKrS\S \4S jr"S S 5r"S S5rg)N) MIMEMultipart)MIMEText)MIMEBase)encoders) formataddr)DictListTuplepdf_pathreturnc[R"U5nURS:XaUR5 gUSnUR 5nUR5 /SQnUHgn[ R "XS5nU(dM"UR5upx[U5n [U5n U S:XaSn U S-n OU S-n U n U SS3n U s $ g![an[SUS U35 S nAgS nAff=f) u`PDF에서 급여명세서 날짜 정보 추출하여 다음달 표시 (예: "08월" → "09월")r 현재달)u+(\d{4})년(\d{1,2})월분\s*급여명세서u((\d{4})년(\d{1,2})월\s*급여명세서u(급여명세서.*?(\d{4})년(\d{1,2})월 02du월u날짜 추출 실패 (): N) fitzopen page_countcloseget_textresearchgroupsint Exceptionprint)r docpagetextpatternspatternmatchyearmonthyear_int month_int next_month next_year month_stres BD:\Development\python\월급명세서_자동배포\email_sender.pyextract_payslip_date_from_pdfr-s(ii! >>Q  IIK1v}}    GIIg,Eu#lln t9J ?!"J (1 I!*QJ (I)#.c2   ! $  &xjA378s*6CA CAC C C5C00C5cl\rSrSrSrS SjrS\4SjrSS\4SjjrS\4S jr S\4S jr S\4S jr S r g) EmailConfig:u!이메일 설정 관리 클래스c:XlUR5UlgN) config_file load_configconfig)selfr3s r,__init__EmailConfig.__init__=s&&&( r cSSSSSSSS.S .n[RRUR5(aF[ URS S S 9n[ R "U5nURU5 S S S 5 URU5 U$!,(df  N!=f![an[SU35 S nANAS nAff=f)u설정 파일 로드smtp.worksmobile.comTnoreply@munjaon.co.kr급여관리팀+{month} 월급명세서 전달드립니다.uo안녕하세요. 항상 수고하고 계신 점 감사드립니다. 이번 달 급여명세서를 첨부하여 전달드립니다. ※ 첨부된 PDF 파일의 비밀번호는 생년월일(8자리)입니다. 예시: 1990년 1월 15일 → 19900115 문의사항이 있으시면 언제든 연락해 주시기 바랍니다. 감사합니다. 급여관리팀 드림)subjectbody) smtp_server smtp_portuse_ssl sender_email sender_nameemail_templaterutf-8encodingNu설정 파일 로드 실패: ) ospathexistsr3rjsonloadupdaterr save_config)r6default_configf loaded_configr+s r,r4EmailConfig.load_configAs23,H   0 77>>$** + + ;$**C'Ba$(IIaLM"))-8C (CB ;5aS9:: ;s5B%(B9B% B"B%"B%% C/CCNr5cUc URn[URSSS9n[R"XSSS9 SSS5 g!,(df  g=f![ an[ SU35 SnAgSnAff=f) u설정 파일 저장NwrIrJF) ensure_asciiindentu설정 파일 저장 실패: )r5rr3rOdumprr)r6r5rTr+s r,rREmailConfig.save_configgsg >[[F 7d&&g>! &%B?>> 7 1!5 6 6 7s3AAA AAA A9!A44A9cURRSS5URRSS5URRSS5S.$)uSMTP 설정 반환rBr;rCr<rDT)serverportrDr5getr6s r,get_smtp_configEmailConfig.get_smtp_configrsEkkoom5KLKKOOK5{{y$7  r9ctURRSS5URRSS5S.$)u발송자 정보 반환rEr=rFr>)emailnamerarcs r,get_sender_infoEmailConfig.get_sender_infozs4[[__^5LMKKOOM3DE  r9c:URRS05$)u이메일 템플릿 반환rGrarcs r,get_email_templateEmailConfig.get_email_templates{{/44r9)r5r3)zemail_config.jsonr2) __name__ __module__ __qualname____firstlineno____doc__r7rr4rRrdrirl__static_attributes__r9r,r/r/:sG+)$T$L 7$ 7    5D5r9r/c\rSrSrSrSS\S\4SjjrS\S\4SjrSS\S \S \S \S \S \4 Sjjr SS\S \S \S \S \S \ \ \44 Sjjr SS\ \S \4SjjrS \ \ \44SjrSrg)PayslipEmailSenderu*급여명세서 이메일 발송 클래스Nusernamepasswordc[5UlXlX lURR 5UlURR 5UlURR5Ul gr2) r/r5rxryrd smtp_configri sender_inforltemplater6rxrys r,r7PayslipEmailSender.__init__sS!m   ;;668;;668 668 r9cXlX lg)u인증 정보 설정N)rxryr~s r,set_credentials"PayslipEmailSender.set_credentialss   r9recipient_emailrecipient_namer custom_subject custom_bodyr c[5nURSnURSn[X45US'XS'U(aUn O?U(a [U5OSn URR SS5n U R U S9n XS 'U=(d URR S S 5n U R US 9n UR[U S S55 U(Ga[RRU5(a[US5n[SS5nURUR55 SSS5 [ R""W5 [RR%U5nUR'S5nSUS3nUR1SU5 UR1SS5 URU5 [3SUS[RR5U5S35 U$[3S U35 U$!,(df  N=f![(a' SSKnUR,R/U5nSU3nNf=f![6an[3SUSU35 SnAU$SnAff=f)!u이메일 메시지 생성rgrhFromTorr@r?)r%SubjectrAuP안녕하세요, {name}님. 월급명세서를 첨부하여 전달드립니다.)rhplainrIrb applicationpdfNasciizattachment; filename=""rzattachment; filename*=UTF-8''zContent-DispositionzContent-Transfer-Encodingbase64uPDF 첨부 성공: z (z bytes)uPDF 첨부 실패 (ru(PDF 파일 없음 또는 경로 문제: )rr|rr-r}rbformatattachrrLrMrNrr set_payloadreadr encode_base64basenameencodeUnicodeEncodeError urllib.parseparsequote add_headerrgetsizer)r6rrr rrmsgrErFr@r%subject_template body_templaterA attachmentpartfilenamefilename_encodedfilename_headerurllibr+s r,create_email_message'PayslipEmailSender.create_email_messagesXo''0 &&v.  +!<=F #D  $G?G1(;[E#}}00(D)Z#M59D$$Z__%67* &&t,77++H5Y'/w'?$(>xj&JO 5G ;XF 4 +H:R8Q7RRYZ[   +H:S<==  >sU I,H >=I<HA$I HI.I I I  I I4I//I4cUR(aUR(dg[RR U5(dSSU34$UR XX4U5nUR S(a2[R"UR SUR S5nOA[R"UR SUR S5nUR5 URURUR5 UR5nURURSX5 UR5 SS US 34$![ an SS [#U 534sS n A $S n A ff=f) u단일 이메일 발송F.인증 정보가 설정되지 않았습니다.Fu)첨부파일을 찾을 수 없습니다: rDr_r`rgT'u>'님에게 이메일이 성공적으로 발송되었습니다.u이메일 발송 실패: N)rxryrLrMrNrr{smtplibSMTP_SSLSMTPstarttlslogin as_stringsendmailr|quitrstr) r6rrr rrrr_r r+s r,send_single_email$PayslipEmailSender.send_single_emailsA}}DMMJww~~h''EhZPP P ?++O*2KQC * ))$*:*:8*DdFVFVW]F^_ d&6&6x&@$BRBRSYBZ[! LL 6==?D OOD,,W5 M KKM1^,,jkk k ?5c!fX>> > ?sDE E;!E60E;6E; email_datac UR(aUR(d /SSS./S.$//S.n[U5nURS(a2[R "URSURS5nOA[R "URSURS5nUR5 URURUR5 [U5HupgURSS 5nURS S 5n URS S 5n [RRU 5(dUS RUU S U 3S.5 M}URXU 5n U R!5n UR#UR$S X5 USRUU U S.5 U(dMU"US-XH5 M UR+5 U$![&a+n US RUU [)U 5S.5 Sn A N[Sn A ff=f![&an UHnURS5USVs/sHoRS5PM Os snfsn;dMAUS RURSS 5URS S 5S[)U 53S.5 M Sn A U$Sn A ff=f)u대량 이메일 발송 Args: email_data: [{"name": "이름", "email": "이메일", "pdf_path": "파일경로"}] progress_callback: 진행상황 콜백 함수 Returns: {"success": [], "failed": []} u 모든 직원r)rherror)successfailedrDr_r`rhrgr ru#첨부파일을 찾을 수 없음: )rhrgrr)rhrgr NrSMTP 서버 연결 실패: )rxrylenr{rrrrr enumeraterbrLrMrNappendrrrr|rrr)r6rprogress_callbackresults total_countr_idatarhrgr rr r+items r,send_bulk_emails#PayslipEmailSender.send_bulk_emailss}}DMM$3>nop  !B/*o :  * ))$*:*:8*DdFVFVW]F^_ d&6&6x&@$BRBRSYBZ[! LL 6$Z0xx+"-88J377>>(33)00$(%*'J8*%U2 !33EJC==?DOOD$4$4W$=uKI&-- $!&$,/%$%a!e[?I1L KKM/!H%,, $!&!$Q. "88F#QZI[+\I[HHV,s1vh!G.# shC3H.1?G60H.2AG6 H. H.6 H+!H&!H.&H++H.. K8K I. - K ;AK  KcUR(aUR(dgURS(a2[R"URSURS5nOA[R "URSURS5nUR 5 URURUR5 UR5 g![anSS[U534sSnA$SnAff=f) uSMTP 서버 연결 테스트rrDr_r`)TuSMTP 서버 연결 성공!FrN) rxryr{rrrrrrrr)r6r_r+s r,test_connection"PayslipEmailSender.test_connectionDs}}DMMJ A * ))$*:*:8*DdFVFVW]F^_ d&6&6x&@$BRBRSYBZ[! LL 6 KKM5 A7Ax@@ @ AsB=C## D-D<DD)r5ryr|r{r}rx)NNr2)rnrorprqrrrr7rrrr boolrr rrrrsrtr9r,rvrvs499s9!!s! AE.2;C;;%(;:=;(+;7D;|?C,0??c?#&?8;?&)?5:495E?BO4:ORVObAtSy!1Ar9rv)rrLemail.mime.multipartremail.mime.textremail.mime.baserrgr email.utilsrtypingrr r rOrrrrrr-r/rvrtr9r,rs[ .$$"$$ *C*C*XI5I5VQAQAr9